下图呈现了敞开了剧本合并功效后打开该网站的HTTP请求情形,ca88亚洲城网站那么在支付过程中作为.NET程序员是怎么着挑选的啊

   
高手速来围观协助答疑~关于ASP.NET MVC Bundling and RequireJS的抉择问题,近来可比困惑,我盼望有一种办法可以整合双方的助益。作为.NET程序员,难道你没有过这地点的迷惑吗?

   
高手速来围观帮忙答疑~关于ASP.NET MVC Bundling and RequireJS的抉择问题,最近可比困惑,我梦想有一种艺术可以构成双方的亮点。作为.NET程序员,难道你从未过这方面的迷离吗?

当前主流浏览器限制客户端对同一域名只好同时提倡6(PS:原文如此)个HTTP连接。 这表示,打开一个网页只可以同时加载6个HTTP请求,在同一个域名下其他的呼吁将被浏览器插手到请求队列中。 在IE浏览器中按F12调出开发人士工具,切换来网络标签,如下图所示,呈现的是一个实例网站关于HTTP资源请求的情事。 

   
因为我深感各自都有利弊,RequireJS的先天不足在于,在付出的时候,你不可能引入压缩后的js或者css,否则不可以调试和改动,而Bundling的话debug格局默认意况下是不收缩,你一宣布到生产成release就机关削减,调试起来十分便利。RequireJS的优点在于可以异步按需加载,还有就是模块化js代码,而Bundling
则是大概粗暴的任何集合成一个文本举行加载,你看不出模块化引用也落实持续按需加载,
那么在支付进程中作为.NET程序员是怎么拔取的吗?能不可能结成双方的长处来利用啊?

   
因为自身觉得各自都有优缺点,RequireJS的瑕疵在于,在开发的时候,你无法引入压缩后的js或者css,否则不可能调试和改动,而Bundling的话debug情势默认意况下是不裁减,你一公布到生产成release就机关削减,调试起来异常有益。RequireJS的优点在于能够异步按需加载,还有就是模块化js代码,而Bundling
则是简单粗暴的任何集合成一个文书举行加载,你看不出模块化引用也兑现持续按需加载,
那么在开发过程中作为.NET程序员是何等挑选的吗?能不可以结成双方的长处来利用啊?

 黑色的进度条呈现的是现阶段呼吁等待的时日,浏览器通过队列来促成其他资源的依次加载。 黄色的进度条呈现的是客户端与服务器建立请求所花费的时光。 肉色条显示的是当下资源从服务器下载完毕所消费的年华。 你可以双击当前恳请查询详细意况。 例如,下图展现的是加载/ Scripts/MyScripts/JavaScript6.js文件整个请求过程的详细意况。 

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

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

 ca88亚洲城网站 1

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

   
倘使你跟自己说您还不了解RequireJS是个神马冬冬?请移步至:http://requirejs.org/docs/api.html

 下面的图样中体现了当前资源在起来事件中被浏览器参预了请求队列。因为浏览器同时呼吁限制的熏陶,当前资源必须等待46皮秒完成上一个HTTP请求才能实施当前的伸手。

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

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

合并

方式一 Bunding+RequireJS混用

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

方式一 Bunding+RequireJS混用

先来探视一个老外的做法,他大致上是这样做的:

联合是ASP.NET 4.5中的新职能,使开发者很容易实现把七个文本合并成一个文本。 你可以实现CSS、javascript脚本以及任何文件的会见功效。合并三个文本表示缩小了HTTP请求的个数,同时提高了页面的加载速度。

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"));

下图展现了启封了剧本合并功效后打开该网站的HTTP请求意况。

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

 ca88亚洲城网站 2

方式二 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

目录结构如下:

ca88亚洲城网站 3ca88亚洲城网站 4ca88亚洲城网站 5

由于在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文件肯定不能够减小合并,不然不能调试了,而生育条件肯定是索要减小和归并的,那么自己想要开发的时候不统一,一宣布到生产就机关合并

ca88亚洲城网站 6

这就是说有二种办法,一种呢是独立写一个批处理脚本,每一回发表到生产的时候就运行一下,一种呢是直接在类型的变通事件中开展布局,假设是debug情势就不裁减合并,固然是release格局则缩减合并

ca88亚洲城网站 7

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

目录结构如下:

ca88亚洲城网站 8ca88亚洲城网站 9ca88亚洲城网站 10

由于在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文件肯定无法压缩合并,不然无法调试了,而生育环境肯定是急需减弱和联合的,那么我想要开发的时候不统一,一通知到生育就自动合并

ca88亚洲城网站 11

这就是说有两种办法,一种啊是独立写一个批处理脚本,每一遍发布到生产的时候就运行一下,一种呢是直接在类型的转变事件中开展布局,如倘若debug格局就不缩小合并,假设是release情势则缩减合并

ca88亚洲城网站 12

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"

减掉功用实现了对javascript脚本和CSS举办削减的机能,它可以去除脚本或样式中不必要的空白和注释,同时可以优化脚本变量名的尺寸。 我们来看下边这段JavaScript函数。

自动构建

批处理自动合并压缩脚本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——工具——增添和翻新:

ca88亚洲城网站 13

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——工具——增加和翻新:

ca88亚洲城网站 14

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

AddAltToImg = function (imageTagAndImageID, imageContext) {
    ///<signature>
    ///<summary> Adds an alt tab to the image
    // </summary>
    //<param name="imgElement" type="String">The image selector.</param>
    //<param name="ContextForImage" type="String">The image context.</param>
    ///</signature>
    var imageElement = $(imageTagAndImageID, imageContext);
    imageElement.attr('alt', imageElement.attr('id').replace(/ID/, ''));
}

缩减后,该函数被联合到了一列: 

AddAltToImg = function (n, t) { var i = $(n, t); i.attr("alt", i.attr("id").replace(/ID/, "")) }

而外剔除注释和剩下的空非凡,其变量名也被浓缩为如下这样: 

原变量

缩短后

imageTagAndImageID

n

imageContext

t

imageElement

i

 

联合和压缩脚本对网站性能的熏陶

下边表格呈现了剧本被合并压缩后对网站性能提升的熏陶。

 

合并和压缩后

未压缩和合并

性能提升

HTTP请求数

9

34

256%

发送字节(KB)

3.26

11.92

266%

响应字节(KB)

388.51

530

36%

耗时(ms)

510 MS

780 MS

53%

 

与未优化的网站相比较,优化后不光缩小了HTTP请求头的高低,同时请求文件的高低也持有显著的缩减。 不同文件的压缩大小是不平等的,该网站的最大的本子文件已经是减掉过的(Scripts\jquery-ui-1.8.11.min.js and Scripts\jquery-1.7.1.min.js) 。 

注:网站的耗时实例是因而Fiddler工具来落实的 。 (从Fiddler的Rules 菜单中选拔Performance 然后采取 Simulate Modem Speeds )。

调节以及压缩Javascript

在支付条件下因为JavaScript脚本不会被缩短和统一,所以调试JavaScript是件很容易的事体(在 Web.config文件中compilation节点设置debug=”true” )。你可以调节一个揭破版本的JavaScript用于生产环境。 使用IE F12开发人士工具,调试JavaScript脚本的方法如下:

1 采取“脚本 ”选项卡,然后选取“最先调剂”按钮。

2 选用你要调节的脚本文件。 

 ca88亚洲城网站 15

3. 挑选“配置” 按钮 ,格式化压缩后的JavaScript,然后采取“格式后的JavaScript”按钮ca88亚洲城网站 16

4. 你还足以经过搜索方法来探寻你需要调剂的函数。 在下边的图片,在寻觅输入框中输入AddAltToImg,搜索结果会以高亮格局显示。 

 ca88亚洲城网站 17

至于开发人士工具调试的更多音讯,请参阅MSDN著作运用开发人士工具调试JavaScript错误.aspx&usg=ALkJrhgQCmu57FL6tKFAP8sDvCjk0d11vA) 。

部署脚本压缩和集合效用

在 Web.config文件中compilation节点设置debug 的值可以拉开或关闭压缩和集合功效。 在底下的XML中, debug设置值为true,可以禁用脚本压缩和合并功用。

<system.web>
    <compilation debug="true" />
    <!-- Lines removed for clarity. -->
</system.web>

一旦要启用脚本压缩和联合,则设置debug 为false 。你可以透过BundleTable 类的EnableOptimizations 属性来掩盖Web.config中的设置。 下边的代码演示了一旦因而BundleTable 来掩盖Web.config文件中的设置: 

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                 "~/Scripts/jquery-{version}.js"));

    // Code removed for clarity.
   BundleTable.EnableOptimizations = true;
}

注意 :除非设置EnableOptimizations为true或设置Web.config文件中compilption 节点的debug属性为false,否则程序是不会联合和压缩文件的。 其余,系统也不会挑选压缩过的剧本,而是精选调试版本。 EnableOptimizations属性的设置将会覆盖Web.config中的设置。

在ASP.NET Web窗体和Web Pages中使用脚本合并和削减功用

在ASP.NET MVC中动用压缩和合并效用

在本节中,大家将创建一个ASP.NET MVC项目,来体验压缩和联合效能。 首先,创立一个新的ASP.NET MVC Internet项目名为MvcBM ,其他装置默认。

打开App_Start \BundleConfig.cs文件并查找RegisterBundles方法,该格局是用来成立、注册和部署需要裁减和优化的台本文件的。下面的代码呈现了有些RegisterBundles方法。

 public static void RegisterBundles(BundleCollection bundles)
{
     bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                 "~/Scripts/jquery-{version}.js"));
         // Code removed for clarity.
}

位置的代码我们制造了一个新的命名为~/bundles/jquery 的JavaScript bundle,并蕴藏了适龄的 脚本文件(用于压缩和合并,这里不包含.vsdoc),还足以通过通配符或根本字来匹配脚本文件夹下不同版本的剧本文件。 ASP.NET MVC 4 中,系统默认集成了jquery-1.7.1.js 库。在release版本中,系统将采用jquery-1.7.1.min.js 包含在品种中。 脚本合并框架遵守以下多少个原则:

  •  当“FileX.min.js” 和“FileX.js” 同时存在时,在release版本中,系统将选择文件名包含“.min”的剧本
  • 请接纳文件名中不含有“.min”的文本进行调节。
  • 请过滤文件名中带有“.vsdoc”的文书(如jQuery-1.7.1-vsdoc.js),该文件仅仅用于VS的智能感知指示。

{version}关键字是用来含有不同版本的jQuery库的。 在那些例子中,使用通配符存在以下多少个便宜:

  • 同意你在不转移原来配置的情景下通过NuGet 更新您的jQuery版本。
  • 机动采取调试版本和文书名中富含“.min”的批发版本。

使用CDN

 CDN jQuery 库将顶替本地jQuery库。 

public static void RegisterBundles(BundleCollection bundles)
{
    //bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
    //            "~/Scripts/jquery-{version}.js"));

    bundles.UseCdn = true;   //enable CDN support

    //add link to jquery on the CDN
    var jqueryCdnPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js";

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

    // Code removed for clarity.
}

在上头的代码中,在发行版大校使用CDN 上的jQuery库,而地面调试的时候利用当地版本jQuery库。 当使用CDN 版本时,你应当创制一个容错机制,预防CDN加载败北的景况。 下边的代码演示了即使在CDN 中的jQuery库加载败北的情景下什么加载本地版本。

</footer>

        @Scripts.Render("~/bundles/jquery")

        <script type="text/javascript">
            if (typeof jQuery == 'undefined') {
                var e = document.createElement('script');
                e.src = '@Url.Content("~/Scripts/jquery-1.7.1.js")';
                e.type = 'text/javascript';
                document.getElementsByTagName("head")[0].appendChild(e);

            }
        </script> 

        @RenderSection("scripts", required: false)
    </body>
</html>

创制一个Bundle

Bundle类Include方法接受一个字符串或数组类型,其中每个字符串是一个虚构的文本路径。其中RegisterBundles方法在App_Start /BundleConfig.cs 文件中示范了什么将四个文本添加到一个文书中:

bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
          "~/Content/themes/base/jquery.ui.core.css",
          "~/Content/themes/base/jquery.ui.resizable.css",
          "~/Content/themes/base/jquery.ui.selectable.css",
          "~/Content/themes/base/jquery.ui.accordion.css",
          "~/Content/themes/base/jquery.ui.autocomplete.css",
          "~/Content/themes/base/jquery.ui.button.css",
          "~/Content/themes/base/jquery.ui.dialog.css",
          "~/Content/themes/base/jquery.ui.slider.css",
          "~/Content/themes/base/jquery.ui.tabs.css",
          "~/Content/themes/base/jquery.ui.datepicker.css",
          "~/Content/themes/base/jquery.ui.progressbar.css",
          "~/Content/themes/base/jquery.ui.theme.css"));

Bundle类的IncludeDirectory方法能够加上一个索引中的所有的(和所有子目录)相匹配文件。 Bundle类IncludeDirectory API是之类所示:

 public Bundle IncludeDirectory(
     string directoryVirtualPath,  // The Virtual Path for the directory.
     string searchPattern)         // The search pattern.

 public Bundle IncludeDirectory(
     string directoryVirtualPath,  // The Virtual Path for the directory.
     string searchPattern,         // The search pattern.
     bool searchSubdirectories)    // true to search subdirectories.

在页面中得以应用Render方法来引用创制好的包(JavaScript对应了Scripts.Render  而CSS对应的是Styles.Render )。上面的代码演示了在Views\Shared\_Layout.cshtml  文件中只要引用CSS和JavaScript的:

<!DOCTYPE html>
<html lang="en">
<head>
    @* Markup removed for clarity.*@    
    @Styles.Render("~/Content/themes/base/css", "~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    @* Markup removed for clarity.*@

   @Scripts.Render("~/bundles/jquery")
   @RenderSection("scripts", required: false)
</body>
</html>

请小心Render方法的参数是一个字符串或数组类型,它同意你在一个方法中添加五个引用。 一般境况下,你可以采用Render方法来机关引用文件而简单了另外HTML标签。你可以应用Url的法子来生成一个文书URL绝对路径。 假使你想行使的HTML5 异步特性。 下面的代码演示了什么使用Url方法引用Modernizr 包。

 <head>
    @*Markup removed for clarity*@
    <meta charset="utf-8" />
    <title>@ViewBag.Title - MVC 4 B/M</title>
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    <meta name="viewport" content="width=device-width" />
    @Styles.Render("~/Content/css")

   @* @Scripts.Render("~/bundles/modernizr")*@

    <script src='@Scripts.Url("~/bundles/modernizr")' async> </script>
</head>

采取通配符“*”来配合文件

在Include 和 IncludeDirectory方法中得以通过通配符“*”来配合路径中某部分均等元素的文书。匹配时不区分路径中的大小写。 IncludeDirectory方法具有搜索子目录的效能。

如若一个连串下有如下JavaScript文件:

  • Scripts\Common\AddAltToImg.js
  • Scripts\Common\ToggleDiv.js
  • Scripts\Common\ToggleImg.js
  • Scripts\Common\Sub1\ToggleLinks.js

ca88亚洲城网站 18

下边的表演示了利用通配符来添加如图所示文件到花色中:

使用通配符

匹配到的文件或异常提示

Include("~/Scripts/Common/*.js")

AddAltToImg.js, ToggleDiv.js, ToggleImg.js

Include("~/Scripts/Common/T*.js")

无效的匹配模式,通配符只能在文件的前缀或后缀中使用。

Include("~/Scripts/Common/*og.*")

无效的匹配模式,一个路径中只能使用一个通配符。

"Include("~/Scripts/Common/T*")

ToggleDiv.js, ToggleImg.js

"Include("~/Scripts/Common/*")

无效的匹配模式,仅使用一个通配符是没有任何意义的。

IncludeDirectory("~/Scripts/Common", "T*")

ToggleDiv.js, ToggleImg.js

IncludeDirectory("~/Scripts/Common", "T*",true)

ToggleDiv.js, ToggleImg.js, ToggleLinks.js

 

常见情状下,大家应当首选通过一体化路径来添加文件,其原因如下:

  • 应用通配符添加脚本其丰硕顺序是按照文件名的字母排序来挨家挨户增长的,有时候因为脚本相互依赖的景观,这种增长情势或者会出错。 CSS和JavaScript文件平常因为互相依赖而不可以遵照文件名排序来添加。为了减小潜在的高风险,你可以因此充裕一个自定义IBundleOrderer.aspx&usg=ALkJrhjmJJjY5MAYiMWZy1ms98jPEtjM3g)来添加文(Gavin)件,然而经过总体文件名来添加文件是最保险的。 例如,以后亟需充裕新文件时,你或许要经过改动 IBundleOrderer.aspx&usg=ALkJrhjmJJjY5MAYiMWZy1ms98jPEtjM3g)类才能实现。
  • 在JavaScript中利用通配符来添加一个目录的具有脚本到项目中恐怕会滋生JavaScript的错误指示。
  • 在加载CSS文件时,可能会并发加载重复的情事,如下所示的例证:

    bundles.Add(new StyleBundle(“~/jQueryUI/themes/baseAll”)

    .IncludeDirectory("~/Content/themes/base", "*.css"));
    

通配符“*.CSS”可以配合文件夹下所有的CSS文件,包括Content\themes\base\jquery.ui.all.css 。Jquery.ui.all.css可能在此外文件中早就存在。

包缓存

集合后的系统安装了HTTP过期时间为一年。假如您再一次打开了一个也没,在服务器的版本为未改变的情事下,服务器将会回来一个HTTP 304状态码,这样浏览器会加载缓存中的文件。 你也足以在IE浏览器下通过按Ctrl + F5来强制刷新页面,这时浏览器会重新请求文件,而不是从缓存中读取(此时服务器响应的HTTP状态码为200)。

下边的图像呈现了在Fiddler中“Caching”选项卡缓存文件的图景 :

 ca88亚洲城网站 19

请求的途径为

http://localhost/MvcBM\_time/bundles/AllMyScripts?v=r0sLDicvP58AIXN\_mc3QdyVvVj5euZNzdsa2N1PKvb81 
其间AllMyScripts是优化后的包名,V = r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81是现阶段包的一个一定字符,用于缓存当前的公文。 只要劳动器端包不改变,ASP.NET应用程序将直接采用AllMyScripts包中的该标记。 假使包中的文件存在变化,ASP.NET程序将会变动一个新的字符串,以便于刷新缓存,使客户端得到新的文件。

If you run the IE9 F12 developer tools and navigate to a previously
loaded page,
IE incorrectly shows conditional GET requests made to each bundle and
the server returning HTTP 304.
You can read why IE9 has problems determining if a conditional request
was made
in the blog entry Using CDNs and Expires to Improve Web Site
Performance. (该段不会翻译)。

在LESS, CoffeeScript, SCSS, Sass中应用脚本优化功用

联合和缩小框架提供了一个体制来拍卖SCSS 、Sass 、LESSCoffeeScript并转移并联合到优化包中。 例如,添加 LESS 文件到您的MVC4连串:

  1. 创制一个文书夹用于添加你的LESS文件。 下边的演示演示了什么样选拔 Content\MyLess folder。 
  2. 经过NuGet来添加合适的包到你的品类中:
  3. 累加一个类,并促成 IBundleTransform.aspx) 接口。然后可以透过下面的代码把LESS添加到你的花色中:

    using System.Web.Optimization;
    
    public class LessTransform : IBundleTransform
    {
        public void Process(BundleContext context, BundleResponse response)
        {
            response.Content = dotless.Core.Less.Parse(response.Content);
            response.ContentType = "text/css";
        }
    }
    
  4. 开创一个Bundle对象,然后添加 LessTransform 和CssMinify.aspx) ,接下去在 App_Start\BundleConfig.cs 中使用 RegisterBundles  方法来注册你的点子。

    var lessBundle = new Bundle("~/My/Less").IncludeDirectory("~/My", "*.less");
    lessBundle.Transforms.Add(new LessTransform());
    lessBundle.Transforms.Add(new CssMinify());
    bundles.Add(lessBundle);
    
  5. 调用Bundle包如下所示:

    @Styles.Render("~/My/Less");
    

联合的注意事项

当你选择Bundle对象来创立一个包时应该用”bundle” 来做前缀,这样可以防止路由争辨 。

比方你的包中存在一个文书更新,程序会变动一个新的查询参数来使客户端在下一回访问的时候取得到最新的本子。在价值观的单身列出文件引用程序中,客户端仅会另行请求修改过的文本,但是在这种新的不二法门下,会再一次下载整个包中的公文,因而,假如你的包平常改变,使用这种统一格局或者并不是一个好的挑三拣四。

文件的联合和压缩首如若为着精益求精页面在第五次加载的时候文件下载所耗费的刻钟。当该页面加载完毕,当再一次打开该页面时,浏览器会从缓存中读取这么些缓存资源(JavaScript,CSS和图像),所以,在开辟同一站点的别样页面,这种方法并不可能增进网站的习性(PS:因为不联合和削减的公文也足以被缓存)。假诺文件的过期设置不正确,浏览器会重复请求该公文,这种场合下合并和压缩文件会提升非第一次打开网页的性质。 有关详细信息,请参阅Using CDNs and Expires to Improve Web Site Performance 。

因此CDN可以改进浏览器同站点同时伸手限制的问题。在CDN环境下,客户端将从不同的域名来呼吁暑假,这些时候同一网站的资源会被缓存在不同的主机商,从而加速网站打开速度,同时CDN还提供了数量缓存的坚守。

System.Web.Optimization命名空间包含在System.Web.Optimization.DLL文件中。 它缩小效能拔取的是WebGrease库(WebGrease.dll),然后利用Antlr3.Runtime.dll。

Additional Resources

· Video: Bundling and Optimizing by Howard Dierking

· Adding Web Optimization to a Web Pages Site.

· Adding Bundling and Minification to Web Forms.

· Performance Implications of Bundling and Minification on Web Browsing by Henrik F Nielsen   ‏@frystyk

· Using CDNs and Expires to Improve Web Site Performance by Rick Anderson   @RickAndMSFT

· Minimize RTT (round-trip times)

Contributors

· Hao Kung

· Howard Dierking

· Diana LaRose

 原文地址:http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

转载请阐明原文地址:http://www.cnblogs.com/lifeil/archive/2013/03/11/2954071.html 

相关文章