Bundling and Minification

原文:http://www.asp.net/mvc/overview/performance/bundling-and-minification
===============================================================================

Bundling 和 minification ASP.NET4.5 为了提高请求响应新增的2个技术.  Bundling and minification 通过减少请求的数量(Boudling的功劳)、减少请求资源的大小(Minification的功劳)提高请求相应的效率

目前大部分浏览器会存在一个对一个域名同时请求数的限制(有的浏览器是最多6个 有的12个). 这意味着当有6个请求正在被处理的时候,其它的请求就得排队等待浏览器处理了. 在下面的图中可以看到使用ie开发工具展示的资源加载时间线.

灰色的部分表示这个请求因为浏览器请求并发数导致的等待发送时间. 黄色的部分表示这个请求被浏览器发送至服务器到服务器开始响应之间的耗费时间. 蓝色的部分表示接受服务器响应数据耗费的时间. 我们可以双击时间线查看详细的信息. 下面的图展示了加载/Scripts/MyScripts/JavaScript6.js的时间线.

Start 事件表示因为浏览器并发请求限制导致的请求排队事件. 在这个例子中请求排队等待了46 milliseconds.

Bundling

Bundling是ASP.NET4.5的新功能 使用它可以非常轻松的把多个文件合并成一个文件. 你可以用它把多个css打包成一个css,也可以把多个js打包成一个js. 越少的文件意味越少的http请求这能提高页面的加载速度.

下面的图片是使用了bundling和minification后加载上面例子中网页的时间线.

Minification

Minification 可以通过去掉不必要的空格、注释、使用更短的变量名来减小css或js的文件大小. 来看下使用minification前的js.

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/, ‘‘));
}

使用minification后,  代码变成了下面这样:

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

发生了什么呢?去掉了注释和不必要的空格, 下面的参数和变量名被重命名为更短的:

Original Renamed
imageTagAndImageID n
imageContext t
imageElement i

Impact of Bundling and Minification

下面的图片展现了一个页面使用b/m前后的区别.

  Using B/M Without B/M Change
File Requests 9 34 256%
KB Sent 3.26 11.92 266%
KB Received 388.51 530 36%
Load Time 510 MS 780 MS 53%

通过bundling我们可以看到发送至服务器的bytes有了显著的减少The bytes sent had a significant reduction with bundling as browsers are fairly verbose with the HTTP headers they apply on requests. 收到来自服务器的bytes变小了,因为大文件 (Scripts\jquery-ui-1.8.11.min.js and Scripts\jquery-1.7.1.min.js) 被最小化了.

Debugging Bundled and Minified JavaScript

在调试模式下调试js很容易,因为在调试模式下js文件不会被打包合并也不会最小化.

Controlling Bundling and Minification

通过修改web.config文件的debug属性可以使用或禁用Bundling 和 minification, debug 设为true bundling 和 minification 被禁用.

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

只要设置debug为false就能启用 bundling 和 minification.我们海可以通过设置BundleTable的EnableOptimizations属性来覆盖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;
}

Note: 除非把 EnableOptimizations 设为  true 或者把web.config的debug设为false,否则文件将不会被bundled or minified. Additionally, the .min version of files will not be used,  the full debug versions will be selected.EnableOptimizations  overrides the debug attribute in the compilation Element  in theWeb.config file

在ASP.NET MVC中使用Bundling和Minification

在这小节中我们创建一个mvc项目展示怎么使用bundling and minification. 首先创建一个mvc项目叫MvcBM.

打开 App_Start\BundleConfig.cs 文件 代码如下.

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

上面的代码创建了一个js包名字叫 ~/bundles/jquery  这包含了适当的文件 (that is debug or minified but not .vsdoc) 在Scripts 文件夹中, 这个包中包含了 "~/Scripts/jquery-{version}.js". 在MVC 4中, 这意味着一个可debug版本的文件 jquery-1.7.1.js 被加到了这个包中. 在发布模式下 jquery-1.7.1.min.js 被包含了进来. bundling 框架有下面几种默认的约定:

  • 选择 “.min” 文件为release版本服务 当“FileX.min.js” 存在的情况下.
  • 在debug环境线选择没有 “.min” 的版本.
  • 忽略“-vsdoc” 文件 (例如 jquery-1.7.1-vsdoc.js), 这些是用来为智能提示服务的.

上面的The {version} 通配符被使用来自动创建合适版本的jQuery Bundler.  在这个例子中使用通配符的好处如下:

  • 在不要修改bundling代码的情况下,使用 NuGet 更新最新版本的 jQuery.
  • 自动选择全版本的或者是".min" 版本的

Using a CDN

下面的代码展示如果和从从CDN上bundle 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.
}

在上面的代码中,release模式下从CDN请求jQuery,在Debug模式下会请求本地的jQuery。 当使用CDN时为了预防加载CDN文件失败,我们应该有一个反馈机制。下面的代码展示了在加载CDN的jQuery时候我们改如何引用本地的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>

Creating a Bundle

Bundle 类的 Include 方法接收一个字符串的数组, 每个字符串都是一个资源的虚拟路径. 下面的代码位于 App_Start\BundleConfig.cs 文件的 RegisterBundles 方法, 展示了如何打包:

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.

在views中使用Render方法就可以使用 Bundles ,  ( Styles.Render 用来使用CSS包 and Scripts.Render 用来使用JS包). 下面的代码位于 Views\Shared\_Layout.cshtml 展示了如何在视图页面使用打包的CSS和JS.

<!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 方法 可以接受多个 string 类型的参数 , 所以你可以在一行代码中添加多个包. 你可以使用 Url 方法 生成 资源的URL. 下面的代码展示如何使用Url 引用 Bundle.

<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>

Using the "*" Wildcard Character to Select Files

Include 方法  和 IncludeDirectory 方法的 search pattern 接受 "*" 通配符.search string 是大小写敏感的. IncludeDirectory 方法 还可以设置是否去子目录中查找匹配.

有这个项目,他有下面的js文件:

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

下面的表格展示对应的方法会加载哪些js:

Call Files Added or Exception Raised
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  接口来自定义顺序  .
  • 有的目录下的文件是为专们的页面准备的,如果在其它页面通配符也把这个文件包含了可能会出现js错误.
  • css文件会import其它的文件这可能导致import的css文件被引用了多次. 举个例子下面的代码创建了个 bundle 打包 jQuery UI主题的CSS 文件 这会导致有的主题文件被加载了2次.
    bundles.Add(new StyleBundle("~/jQueryUI/themes/baseAll")
        .IncludeDirectory("~/Content/themes/base", "*.css"));

    "*.css" 通配符会包含base文件夹下所有的css文件 包括 Content\themes\base\jquery.ui.all.css 文件. jquery.ui.all.css  文件又 imports 了其它的 CSS 文件.

Bundle 缓存

Bundles 默认会从创建开始缓存一年.

http://localhost/MvcBM_time/bundles/AllMyScripts?v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81 
请求名为 AllMyScripts 的  bundle url包含一个查询参数 v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81. 查询参数 v 有一个值他被缓存所使用.  只要你的bundle没有改变, ASP.NET application 会始终通过v的这个值来请求 AllMyScripts  bundle. 如果bundle中的任何文件发生了改变, the ASP.NET 会生成一个新的值, 这样浏览器就会去请求这个新的 bundle.

时间: 2024-08-01 18:45:52

Bundling and Minification的相关文章

Bundling and Minification(转)

原文地址:https://go.microsoft.com/fwlink/?LinkId=301862 Bundling and minification are two techniques you can use in ASP.NET 4.5 to improve request load time. Bundling and minification improves load time by reducing the number of requests to the server an

ASP.NET MVC Bundling and RequireJS

高手速来围观帮忙解惑~关于ASP.NET MVC Bundling and RequireJS的取舍问题,最近比较困惑,我希望有一种方式可以结合两者的优点.作为.NET程序员,难道你没有过这方面的困惑吗? 因为我感觉各自都有优缺点,RequireJS的缺点在于,在开发的时候,你不能引入压缩后的js或者css,否则无法调试和修改,而Bundling的话debug模式默认情况下是不压缩,你一发布到生产成release就自动压缩,调试起来非常方便.RequireJS的优点在于可以异步按需加载,还有就是

MVC学习系列14--Bundling And Minification【捆绑和压缩】--翻译国外大牛的文章

这个系列是,基础学习系列的最后一部分,这里,我打算翻译一篇国外的技术文章结束这个基础部分的学习:后面打算继续写深入学习MVC系列的文章,之所以要写博客,我个人觉得,做技术的,首先得要懂得分享,说不定你自己以为正确的东西,存在瑕疵,分享出来,大家也可以互相进步.这样整个生态圈也会越来越好.不是么?   好了,闲话扯远了,下面开始正题吧,一下是英文和中文对照,翻译的不好,请见谅. This article introduces how to improve ASP.NET MVC Applicati

The Modern JavaScript Developer’s Toolbox

The Modern JavaScript Developer’s Toolbox Posted by David Haney on Mar 09, 2015 The Web Platform has gone a long way since HTML5 was first made popular and people started looking into JavaScript as a language that could do build complex apps. Many AP

常用工具整理

代码编辑 Cmd Markdown 免费在线Markdown编辑器,一直再用,很不错. Cmd Markdown下载地址:X86 | X64 反编译 dotPeek dotPeek 是 .NET 平台的一款免费的反编译工具,支持反编译 .NET 1.0 ~ 4.0 到 C# 代码. dotPeek下载地址:X86 | X64 | 使用说明 JustDecompile Telerik 公司开发的 .NET 程序集反编译引擎,为反编译工具 JustDecompile 提供反编译功能. JustDec

ASP.NET 5中的ASP.NET Bundles跑到哪里去了?

(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 众所周知,在ASP.NET MVC中很早就存在一个所谓的"bundling and minification"的特性,那么在ASP.NET 5中,这个特性跑哪里去了?待今天推荐的文章来分解. 在使用ASP.NET MVC4.5开发Web应用的时候,为了加速加载客户端的一些资源(比如js和css),需要对这些js和css进行打包和压缩来减少浏览器对服务器的请求次数.具体做法就是在A

ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view)

原文:ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view) 在本节中,您将验证电影控制器生成的编辑方法(Edit action methods)和视图.但是首先将修改点代码,使得发布日期属性(ReleaseDate)看上去更好.打开Models \ Movie.cs文件,并添加高亮行如下所示: using System; using System.ComponentModel.DataAnnotations; using System.Data.

Fundamentals of MVC

Chapter 1 Fundamentals of MVC Microsoft's Web Development Platforms Understanding the past can be a big help in appreciating the present. 1.ASP asked for features such as improved code reuse,better separation of concerns,and easier application of obj

面向.Net程序员的前端优化

背景 作为web开发人员大家大多了解一些网站的性能优化方法,其实大部分方法都不复杂,例如针对前端js和css的压缩来减少请求大小,通过合并来减少请求次数.这里站在.Net后端程序员的角度来看一下如何最简单快捷的处理这一类需求. 全文分3节 combres,mvc4的Bundle,以及2者的对比和个人的意见观点. 弄了个很张扬的点赞样式,如果觉得很想吐槽请告诉我,我删掉... Combres Combres是一个.NET程序库,能够缩小,压缩,合并,以及缓存的JavaScript和CSS资源,AS