那么在开发进度中作为.NET程序员是怎么着挑选的吧,在ASP.NET MVC项目中贯彻js和css的模块化

   
高手速来围观支持答疑~关于ASP.NET MVC Bundling and RequireJS的选料难题,目前比较可疑,我盼望有一种格局得以组合双方的独到之处。作为.NET程序员,难道你没有过那上边的迷离吗?

   
高手速来围观辅助答疑~关于ASP.NET MVC Bundling and RequireJS的拔取难题,近年来可比思疑,我希望有一种艺术得以组成双方的亮点。作为.NET程序员,难道你从未过那方面的迷惑吗?

   
因为我感到各自都有利弊,RequireJS的弱点在于,在付出的时候,你不可能引入压缩后的js或者css,否则无法调试和改动,而Bundling的话debug形式默许情状下是不收缩,你一发布到生产成release就自行削减,调试起来格外有利于。RequireJS的长处在于可以异步按需加载,还有就是模块化js代码,而Bundling
则是粗略凶暴的所有联合成一个文书举行加载,你看不出模块化引用也兑现持续按需加载,
那么在支付进程中作为.NET程序员是怎么选拔的啊?能不可能构成双方的亮点来使用呢?

   
因为自己深感各自都有利弊,RequireJS的症结在于,在付出的时候,你不可能引入压缩后的js或者css,否则不能调试和改动,而Bundling的话debug方式默许情状下是不促销扣,你一发布到生产成release就自动削减,调试起来尤其方便。RequireJS的优点在于可以异步按需加载,还有就是模块化js代码,而Bundling
则是概括暴虐的一体联合成一个文书举行加载,你看不出模块化引用也兑现持续按需加载,
那么在支付进程中作为.NET程序员是哪些选取的吗?能否够构成双方的亮点来利用啊?

    目标:在ASP.NET MVC项目中落实js和css的模块化,并协助压缩合并。

    对象:在ASP.NET MVC项目中贯彻js和css的模块化,并协助压缩合并。

   
如若您跟我说你还不亮堂RequireJS是个神马冬冬?请移步至:http://requirejs.org/docs/api.html

   
如若你跟自己说您还不领会RequireJS是个神马冬冬?请移步至:http://requirejs.org/docs/api.html

    项目目录结构沿用上一篇ASP.NET MVC
重写RazorViewEngine已毕多主旨切换

    项目目录结构沿用上一篇ASP.NET MVC
重写RazorViewEngine达成多焦点切换

方式一 Bunding+RequireJS混用

先来看看一个老外的做法,他大致上是那样做的:

方式一 Bunding+RequireJS混用

先来看看一个老外的做法,他大致上是那样做的:

Bundling部分

App_Start/BundleConfig.cs:

bundles.Add(new ScriptBundle("~/bundles/test").Include(
                   "~/Scripts/jquery-{version}.js",
                   "~/Scripts/q.js",
                   "~/Scripts/globalize.js"));

Bundling部分

App_Start/BundleConfig.cs:

bundles.Add(new ScriptBundle("~/bundles/test").Include(
                   "~/Scripts/jquery-{version}.js",
                   "~/Scripts/q.js",
                   "~/Scripts/globalize.js"));

RequireJS配置部分

在ASP.NET MVC项目中,大家一般是在_Layout母版页中添加js引用

    <script src="~/Scripts/require.js"></script>
    @if (!HttpContext.Current.IsDebuggingEnabled)
    {
        <script>
            requirejs.config({
                bundles: {
                    '@Scripts.Url("~/bundles/test").ToString()': [
                        'jquery',
                        'globalize',
                        'q']
                }
            });
        </script>
    }

个体点评:很不优雅的落到实处方式,说好的模块化呢?而且并没有提供完整的应用程序解决方案。

老外原文地址:ASP.NET MVC Bundling and Minification with
RequireJS

RequireJS配置部分

在ASP.NET MVC项目中,大家一般是在_Layout母版页中添加js引用

    <script src="~/Scripts/require.js"></script>
    @if (!HttpContext.Current.IsDebuggingEnabled)
    {
        <script>
            requirejs.config({
                bundles: {
                    '@Scripts.Url("~/bundles/test").ToString()': [
                        'jquery',
                        'globalize',
                        'q']
                }
            });
        </script>
    }

个体点评:很不优雅的兑现格局,说好的模块化呢?而且并没有提供完整的应用程序解决方案。

鬼子原文地址:ASP.NET MVC Bundling and Minification with
RequireJS

方式二 RequireJS.NET

唯独随后我就发现了一个插件RequireJS.NET

什么是RequireJS.NET?

RequireJS.NET让每一个C#程序员可以来营造JavaScript代码,不须要所有高级的js编程技能就可以来驾驭和选择。

在ASP.NET MVC中使用RequireJS的优势:

  • 让JavaScript代码尤其可复用
  • 有限支撑的目的和看重关系管理
  • 适用于大型复杂的利用
  • 异步加载JavaScript文件

民用点评:安装那个设置那多少个,而且相比死板,我完全可以友善写代码落成它的功效,而且越加灵活,想怎么改怎么改。

RequireJS.NET的运用请参见:Getting started with RequireJS for ASP.NET
MVC

方式二 RequireJS.NET

不过随着我就发现了一个插件RequireJS.NET

什么是RequireJS.NET?

RequireJS.NET让每一个C#程序员能够来打造JavaScript代码,不必要有所高级的js编程技能就可以来领会和动用。

在ASP.NET MVC中使用RequireJS的优势:

  • 让JavaScript代码尤其可复用
  • 有限支撑的目的和凭借关系管理
  • 适用于大型复杂的运用
  • 异步加载JavaScript文件

个人点评:安装这一个装置这几个,而且比较蠢笨,我一心可以协调写代码完毕它的功效,而且进一步灵敏,想怎么改怎么改。

RequireJS.NET的使用请参见:Getting started with RequireJS for ASP.NET
MVC

本身的贯彻情势

    接下去,我将隆重推出我的兑现方式自身的做法是:甩掉ASP.NET
MVC自带的Bundling效用,因为它太傻瓜、太野蛮了,可是可以将RequireJS and
R.js
很投机的合龙在ASP.NET
MVC项目中来。尽管RequireJS看上去在单页应用的情景下用起来越发便宜,可是在应用程序场景下也是同等适用的,只要你愿意承受它的那种方法。

动用技术: using RequireJS and R.js

目录结构如下:

图片 1图片 2图片 3

出于在ASP.NET
MVC项目中,有模板页_Layout.cshtml,那么自己能够把一部分公用调用的东西直接放到模板页中,那里自己透过Html的恢弘方法举行了打包

css的调用:

     <link rel="stylesheet" href="@Html.StylesPath("main.css")" />

js的调用:

    <script src="@Url.Content("~/themes/default/content/js/require.js")"></script>
    <script>   @Html.ViewSpecificRequireJS()</script>
        @RenderSection("scripts", required: false)

RequireJsHelpers:

using System.IO;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace Secom.Emx.WebApp
{
    public static class RequireJsHelpers
    {
        private static MvcHtmlString RequireJs(this HtmlHelper helper, string config, string module)
        {
            var require = new StringBuilder();
            string jsLocation = "/themes/default/content/release-js/";
#if DEBUG
            jsLocation = "/themes/default/content/js/";
#endif

            if (File.Exists(helper.ViewContext.HttpContext.Server.MapPath(Path.Combine(jsLocation, module + ".js"))))
            {
                require.AppendLine("require( [ \"" + jsLocation + config + "\" ], function() {");
                require.AppendLine("    require( [ \"" + module + "\",\"domReady!\"] ); ");
                require.AppendLine("});");
            }

            return new MvcHtmlString(require.ToString());
        }

        public static MvcHtmlString ViewSpecificRequireJS(this HtmlHelper helper)
        {
            var areas = helper.ViewContext.RouteData.DataTokens["area"];
            var action = helper.ViewContext.RouteData.Values["action"];
            var controller = helper.ViewContext.RouteData.Values["controller"];

            string url = areas == null? string.Format("views/{0}/{1}", controller, action): string.Format("views/areas/{2}/{0}/{1}", controller, action, areas);

            return helper.RequireJs("config.js", url);
        }
        public static string StylesPath(this HtmlHelper helper, string pathWithoutStyles)
        {
#if (DEBUG)
            var stylesPath = "~/themes/default/content/css/";
#else
            var stylesPath =  "~/themes/default/content/release-css/";
#endif
            return VirtualPathUtility.ToAbsolute(stylesPath + pathWithoutStyles);
        }
    }
}

再来看下大家的js主文件config.js

requirejs.config({
    baseUrl: '/themes/default/content/js',
    paths: {
        "jquery": "jquery.min",
        "jqueryValidate": "lib/jquery.validate.min",
        "jqueryValidateUnobtrusive": "lib/jquery.validate.unobtrusive.min",
        "bootstrap": "lib/bootstrap.min",
        "moment": "lib/moment.min",
        "domReady": "lib/domReady",
    },
    shim: {
        'bootstrap': {
            deps: ['jquery'],
            exports: "jQuery.fn.popover"
        },
        "jqueryValidate": ["jquery"],
        "jqueryValidateUnobtrusive": ["jquery", "jqueryValidate"]
    }
});

 在支付条件,大家的css文件肯定不可能压缩合并,不然不可以调试了,而生产条件肯定是急需减弱和集合的,那么我想要开发的时候不统一,一发布到生育就自动合并

图片 4

那么有二种艺术,一种啊是单身写一个批处理脚本,每一次公布到生育的时候就运行一下,一种啊是一向在品种的更动事件中进行陈设,假若是debug形式就不降价扣合并,即使是release情势则收缩合并

图片 5

if $(ConfigurationName) == Release node "$(ProjectDir)themes\default\content\build\r.js" -o "$(ProjectDir)themes\default\content\build\build-js.js"
if $(ConfigurationName) == Release node "$(ProjectDir)themes\default\content\build\r.js" -o "$(ProjectDir)themes\default\content\build\build-css.js"

自我的落到实处形式

    接下去,我将隆重推出我的贯彻方式本身的做法是:屏弃ASP.NET
MVC自带的Bundling成效,因为它太傻瓜、太野蛮了,不过可以将RequireJS and
R.js
很温馨的合并在ASP.NET
MVC项目中来。就算RequireJS看上去在单页应用的场景下用起来非凡便于,可是在应用程序场景下也是一样适用的,只要你愿意承受它的那种艺术。

使用技术: using RequireJS and R.js

目录结构如下:

图片 6图片 7图片 8

由于在ASP.NET
MVC项目中,有模板页_Layout.cshtml,那么自己可以把部分公用调用的东西直接放到模板页中,那里自己通过Html的伸张方法开展了打包

css的调用:

     <link rel="stylesheet" href="@Html.StylesPath("main.css")" />

js的调用:

    <script src="@Url.Content("~/themes/default/content/js/require.js")"></script>
    <script>   @Html.ViewSpecificRequireJS()</script>
        @RenderSection("scripts", required: false)

RequireJsHelpers:

using System.IO;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace Secom.Emx.WebApp
{
    public static class RequireJsHelpers
    {
        private static MvcHtmlString RequireJs(this HtmlHelper helper, string config, string module)
        {
            var require = new StringBuilder();
            string jsLocation = "/themes/default/content/release-js/";
#if DEBUG
            jsLocation = "/themes/default/content/js/";
#endif

            if (File.Exists(helper.ViewContext.HttpContext.Server.MapPath(Path.Combine(jsLocation, module + ".js"))))
            {
                require.AppendLine("require( [ \"" + jsLocation + config + "\" ], function() {");
                require.AppendLine("    require( [ \"" + module + "\",\"domReady!\"] ); ");
                require.AppendLine("});");
            }

            return new MvcHtmlString(require.ToString());
        }

        public static MvcHtmlString ViewSpecificRequireJS(this HtmlHelper helper)
        {
            var areas = helper.ViewContext.RouteData.DataTokens["area"];
            var action = helper.ViewContext.RouteData.Values["action"];
            var controller = helper.ViewContext.RouteData.Values["controller"];

            string url = areas == null? string.Format("views/{0}/{1}", controller, action): string.Format("views/areas/{2}/{0}/{1}", controller, action, areas);

            return helper.RequireJs("config.js", url);
        }
        public static string StylesPath(this HtmlHelper helper, string pathWithoutStyles)
        {
#if (DEBUG)
            var stylesPath = "~/themes/default/content/css/";
#else
            var stylesPath =  "~/themes/default/content/release-css/";
#endif
            return VirtualPathUtility.ToAbsolute(stylesPath + pathWithoutStyles);
        }
    }
}

再来看下大家的js主文件config.js

requirejs.config({
    baseUrl: '/themes/default/content/js',
    paths: {
        "jquery": "jquery.min",
        "jqueryValidate": "lib/jquery.validate.min",
        "jqueryValidateUnobtrusive": "lib/jquery.validate.unobtrusive.min",
        "bootstrap": "lib/bootstrap.min",
        "moment": "lib/moment.min",
        "domReady": "lib/domReady",
    },
    shim: {
        'bootstrap': {
            deps: ['jquery'],
            exports: "jQuery.fn.popover"
        },
        "jqueryValidate": ["jquery"],
        "jqueryValidateUnobtrusive": ["jquery", "jqueryValidate"]
    }
});

 在开发环境,大家的css文件肯定不可以减少合并,不然不能调试了,而生育环境肯定是亟需减小和统一的,那么我想要开发的时候不合并,一布告到生产就自行合并

图片 9

那么有二种办法,一种啊是单独写一个批处理脚本,每一次宣布到生产的时候就运行一下,一种呢是直接在类型的转移事件中展开部署,假若是debug情势就不收缩合并,即使是release情势则缩减合并

图片 10

if $(ConfigurationName) == Release node "$(ProjectDir)themes\default\content\build\r.js" -o "$(ProjectDir)themes\default\content\build\build-js.js"
if $(ConfigurationName) == Release node "$(ProjectDir)themes\default\content\build\r.js" -o "$(ProjectDir)themes\default\content\build\build-css.js"

机关构建

批处理自动合并压缩脚本build.bat:

@echo off
echo start build js
node.exe r.js -o build-js.js
echo end build js
echo start build css
node.exe r.js -o build-css.js
echo end build css
echo. & pause

因为我的js文件是和控制器中的view视图界面一一对应的,那么我索要一个动态的js打造脚本,那里自己动用强劲的T4模板来完毕,新建一个文件模板build-js.tt,借使你的VS没有T4的智能提醒,你必要设置一个VS插件,打开VS——工具——增加和翻新:

图片 11

T4模板代码如下:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Configuration" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".js" #>
({
    appDir: '<#= relativeBaseUrl #>',
    baseUrl: './',
    mainConfigFile: '<#= relativeBaseUrl #>/config.js',
    dir: '../release-js',
    modules: [
    {
        name: "config",
        include: [
            // These JS files will be on EVERY page in the main.js file
            // So they should be the files we will almost always need everywhere
            "domReady",
            "jquery",
            "jqueryValidate",
            "jqueryValidateUnobtrusive",
            "bootstrap",
            "moment"
            ]
    },
    <# foreach(string path in System.IO.Directory.GetFiles(this.Host.ResolvePath(relativeBaseUrl+"/views"), "*.js", System.IO.SearchOption.AllDirectories)) { #>
{
       name: '<#= GetRequireJSName(path) #>'
    },
    <# } #>
],
    onBuildRead: function (moduleName, path, contents) {
        if (moduleName = "config") {
            return contents.replace("/themes/default/content/js","/themes/default/content/release-js")
        }
        return contents;
    },
})

<#+ 
    public const string relativeBaseUrl = "../js";

    public string GetRequireJSName(string path){
    var relativePath = Path.GetFullPath(path).Replace(Path.GetFullPath(this.Host.ResolvePath("..\\js\\")), "");
    return Path.Combine(Path.GetDirectoryName(relativePath), Path.GetFileNameWithoutExtension(relativePath)).Replace("\\", "/");
} #>

透过T4模板生产的营造脚本如下:

({
    appDir: '../js',
    baseUrl: './',
    mainConfigFile: '../js/config.js',
    dir: '../release-js',
    modules: [
    {
        name: "config",
        include: [
            // These JS files will be on EVERY page in the main.js file
            // So they should be the files we will almost always need everywhere
            "domReady",
            "jquery",
            "jqueryValidate",
            "jqueryValidateUnobtrusive",
            "bootstrap",
            "moment"
            ]
    },
    {
       name: 'views/areas/admin/default/index'
    },
    {
       name: 'views/home/index'
    },
    {
       name: 'views/home/login'
    },
    ],
    onBuildRead: function (moduleName, path, contents) {
        if (moduleName = "config") {
            return contents.replace("/themes/default/content/js","/themes/default/content/release-js")
        }
        return contents;
    },
})

 个人点评:灵活性很好,想怎么整怎么整,而且可以很好的支撑每日创设和不断集成。

 有时候,总是会在某一瞬间就有新奇的想法,那就是程序员,借使您以为我的篇章对您有帮衬或者启发,请推荐一下呢!如果有协调的想法也请提出来,大家一起切磋!

 后记:我自然还想给每js和css的url路径后缀添加版本号来落到实处客户端缓存的自动更新,如?v=1.0,可是后边想了下浏览器本身就自带客户端缓存,所以就先没有添加,如若真有亟待,可以随时补上。

 调整后的门类源码:https://git.coding.net/zouyujie/Smp.git

电动创设

批处理自动合并压缩脚本build.bat:

@echo off
echo start build js
node.exe r.js -o build-js.js
echo end build js
echo start build css
node.exe r.js -o build-css.js
echo end build css
echo. & pause

因为自己的js文件是和控制器中的view视图界面一一对应的,那么自己索要一个动态的js打造脚本,那里我动用强劲的T4模板来兑现,新建一个文书模板build-js.tt,倘诺您的VS没有T4的智能提示,你需求安装一个VS插件,打开VS——工具——扩张和更新:

图片 12

T4模板代码如下:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Configuration" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".js" #>
({
    appDir: '<#= relativeBaseUrl #>',
    baseUrl: './',
    mainConfigFile: '<#= relativeBaseUrl #>/config.js',
    dir: '../release-js',
    modules: [
    {
        name: "config",
        include: [
            // These JS files will be on EVERY page in the main.js file
            // So they should be the files we will almost always need everywhere
            "domReady",
            "jquery",
            "jqueryValidate",
            "jqueryValidateUnobtrusive",
            "bootstrap",
            "moment"
            ]
    },
    <# foreach(string path in System.IO.Directory.GetFiles(this.Host.ResolvePath(relativeBaseUrl+"/views"), "*.js", System.IO.SearchOption.AllDirectories)) { #>
{
       name: '<#= GetRequireJSName(path) #>'
    },
    <# } #>
],
    onBuildRead: function (moduleName, path, contents) {
        if (moduleName = "config") {
            return contents.replace("/themes/default/content/js","/themes/default/content/release-js")
        }
        return contents;
    },
})

<#+ 
    public const string relativeBaseUrl = "../js";

    public string GetRequireJSName(string path){
    var relativePath = Path.GetFullPath(path).Replace(Path.GetFullPath(this.Host.ResolvePath("..\\js\\")), "");
    return Path.Combine(Path.GetDirectoryName(relativePath), Path.GetFileNameWithoutExtension(relativePath)).Replace("\\", "/");
} #>

通过T4模板生产的打造脚本如下:

({
    appDir: '../js',
    baseUrl: './',
    mainConfigFile: '../js/config.js',
    dir: '../release-js',
    modules: [
    {
        name: "config",
        include: [
            // These JS files will be on EVERY page in the main.js file
            // So they should be the files we will almost always need everywhere
            "domReady",
            "jquery",
            "jqueryValidate",
            "jqueryValidateUnobtrusive",
            "bootstrap",
            "moment"
            ]
    },
    {
       name: 'views/areas/admin/default/index'
    },
    {
       name: 'views/home/index'
    },
    {
       name: 'views/home/login'
    },
    ],
    onBuildRead: function (moduleName, path, contents) {
        if (moduleName = "config") {
            return contents.replace("/themes/default/content/js","/themes/default/content/release-js")
        }
        return contents;
    },
})

 个人点评:灵活性很好,想怎么整怎么整,而且可以很好的辅助天天打造和不止集成。

 有时候,总是会在某一须臾间就有新奇的想法,这就是程序员,如若你以为自身的稿子对您有赞助或者启发,请推荐一下吗!若是有和好的想法也请提出来,大家齐声啄磨!

 后记:我本来还想给每js和css的url路径后缀添加版本号来促成客户端缓存的自动更新,如?v=1.0,可是前边想了下浏览器本身就自带客户端缓存,所以就先没有增进,若是真有亟待,可以每日补上。

 调整后的系列源码:https://git.coding.net/zouyujie/Smp.git

相关文章