原文: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.

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

  

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

  1. 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 被禁用.

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

  

只要设置debug为false就能启用 bundling 和 minification.我们还可以通过设置BundleTable的EnableOptimizations属性来覆盖web.config的设置.

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

  

Note: 除非把 EnableOptimizations 设为  true 或者把web.config的debug设为false,否则文件将不会被bundled or minified.

在ASP.NET MVC中使用Bundling和Minification

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

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

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

  

上面的代码创建了一个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.

  1. public static void RegisterBundles(BundleCollection bundles)
  2. {
  3. //bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
  4. // "~/Scripts/jquery-{version}.js"));
  5.  
  6. bundles.UseCdn = true; //enable CDN support
  7.  
  8. //add link to jquery on the CDN
  9. var jqueryCdnPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js";
  10.  
  11. bundles.Add(new ScriptBundle("~/bundles/jquery",
  12. jqueryCdnPath).Include(
  13. "~/Scripts/jquery-{version}.js"));
  14.  
  15. // Code removed for clarity.
  16. }

  

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

  1. </footer>
  2.  
  3. @Scripts.Render("~/bundles/jquery")
  4.  
  5. <script type="text/javascript">
  6. if (typeof jQuery == 'undefined') {
  7. var e = document.createElement('script');
  8. e.src = '@Url.Content("~/Scripts/jquery-1.7.1.js")';
  9. e.type = 'text/javascript';
  10. document.getElementsByTagName("head")[0].appendChild(e);
  11.  
  12. }
  13. </script>
  14.  
  15. @RenderSection("scripts", required: false)
  16. </body>
  17. </html>

  

Creating a Bundle

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

  1. bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
  2. "~/Content/themes/base/jquery.ui.core.css",
  3. "~/Content/themes/base/jquery.ui.resizable.css",
  4. "~/Content/themes/base/jquery.ui.selectable.css",
  5. "~/Content/themes/base/jquery.ui.accordion.css",
  6. "~/Content/themes/base/jquery.ui.autocomplete.css",
  7. "~/Content/themes/base/jquery.ui.button.css",
  8. "~/Content/themes/base/jquery.ui.dialog.css",
  9. "~/Content/themes/base/jquery.ui.slider.css",
  10. "~/Content/themes/base/jquery.ui.tabs.css",
  11. "~/Content/themes/base/jquery.ui.datepicker.css",
  12. "~/Content/themes/base/jquery.ui.progressbar.css",
  13. "~/Content/themes/base/jquery.ui.theme.css"));

  

Bundle 类的 IncludeDirectory 方法 可以添加一个目录下所有匹配模式的文件(子目录可选) .  Bundle 类的 IncludeDirectory API 如下:

  1. public Bundle IncludeDirectory(
  2. string directoryVirtualPath, // The Virtual Path for the directory.
  3. string searchPattern) // The search pattern.
  4.  
  5. public Bundle IncludeDirectory(
  6. string directoryVirtualPath, // The Virtual Path for the directory.
  7. string searchPattern, // The search pattern.
  8. bool searchSubdirectories) // true to search subdirectories.

  

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

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. @* Markup removed for clarity.*@
  5. @Styles.Render("~/Content/themes/base/css", "~/Content/css")
  6. @Scripts.Render("~/bundles/modernizr")
  7. </head>
  8. <body>
  9. @* Markup removed for clarity.*@
  10.  
  11. @Scripts.Render("~/bundles/jquery")
  12. @RenderSection("scripts", required: false)
  13. </body>
  14. </html>

  

注意 Render 方法 可以接受多个 string 类型的参数 , 所以你可以在一行代码中添加多个包. 你可以使用 Url 方法 生成 资源的URL. 下面的代码展示如何使用Url 引用 Bundle.

  1. <head>
  2. @*Markup removed for clarity*@
  3. <meta charset="utf-8" />
  4. <title>@ViewBag.Title - MVC 4 B/M</title>
  5. <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
  6. <meta name="viewport" content="width=device-width" />
  7. @Styles.Render("~/Content/css")
  8.  
  9. @* @Scripts.Render("~/bundles/modernizr")*@
  10.  
  11. <script src='@Scripts.Url("~/bundles/modernizr")' async> </script>
  12. </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次.
    1. bundles.Add(new StyleBundle("~/jQueryUI/themes/baseAll")
    2. .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.

[译]Bundling and Minification的更多相关文章

  1. [Bundling and Minification ] 四、总结

    一.ASP.NET MVC 里面提供了一个默认的绑定集合BundleTable.Bundles 位于System.Web.Optimization下的静态类BundleTable中的一个静态变量.以下 ...

  2. asp.net mvc4 使用 System.Web.Optimization 对javascript和style的引入、代码合并和压缩的优化(ScriptBundle,StyleBundle,Bundling and Minification )

    Bundling and Minification两个单词对今天的内容有个比较好的总结. 问题所在 一. 在asp.net包括mvc项目中,引入js和css也许有人认为是个很容易和很简单操作的事情,v ...

  3. [Bundling and Minification ] 二、绑定的作用

    本篇接上一篇[Bundling and Minification ] 一.如何绑定 Bundling的作用有二,一是合并文件减少资源请求的个数缩短资源请求的时间.二是自动更新到最新js或者css,当合 ...

  4. CSS and JavaScript Bundling and Minification in ASP.NET 4.5

    ASP.NET 4.5 includes a new feature to minify and bundle CSS and JavaScript within your web applicati ...

  5. [Bundling and Minification ] 一、如何绑定

    绑定和压缩(缩小)是ASP.NET 4.5出现的用来提高程序性能的两个重要的技术.绑定(Bundling)是将多个文件合并为一个文件,压缩(Minification)主要是将文件缩小,如Js .CSS ...

  6. [Bundling and Minification ] 三、缩小

    Minification 缩小,将文档的Size减小.主要是通过一下方式缩小文档的Size: 1.移除没用的空行 . 2.删除代码注释. 3.缩短js变量的名称,将变量名用一个字母表示.

  7. WebForm捆绑压缩js和css(WebForm Bundling and Minification)

    .net framework 4以上,可以使用Microsoft.AspNet.Web.Optimization 新建4.0项目 Nuget搜索optimization,安装第一个包 加入Bundle ...

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

    这个系列是,基础学习系列的最后一部分,这里,我打算翻译一篇国外的技术文章结束这个基础部分的学习:后面打算继续写深入学习MVC系列的文章,之所以要写博客,我个人觉得,做技术的,首先得要懂得分享,说不定你 ...

  9. MVC4的bundling功能简介

    Bundling and Minification是asp.net mvc4中一项可以减少用户请求等待时间,提升用户体验的一项技术.在VS2010中新建MVC4项目是,如果选择"基本&quo ...

随机推荐

  1. Jenkins 2.x新建节点配置(Windows)

    2.0版本以上默认加入了权限插件,所以在进入主界面时是需要登录的. 一.主界面->[系统管理]->[管理节点]->[新建节点],进行节点的添加: 二.输入节点名称,已经选择[Perm ...

  2. crawler: 爬虫的基本结构

    目前我所知道的爬虫在获取页面信息上,分为静态爬虫和动态爬虫:静态爬虫主要用于获取静态页面,获取速度一般也比较快:但是现在很多网站的页面都是采用动态页面,当我们用爬虫去获取信息的时候,页面的信息可能还没 ...

  3. shell命令date

    某个标准时间转换为unix时间戳 date -d '2015-10-20 15:07:02' +%s unix时间戳转换为对应的标准时间 date -d @1445324822 date " ...

  4. hibernate-criteria查询

    Criteria查询是Hibernate提供的一种查询方式 下面就一个员工和部门来列一个总体的例子 package Test; import java.util.ArrayList; import j ...

  5. Python 培训之MySql

    1. Install  1.1 install mysql sudo apt-get install lamp-server^ (tip: Set password) 1.2 install MySQ ...

  6. 【原】ajaxupload.js上传报错处理方法

    相信大家在工作中经常用到文件上传的操作,因为我是搞前端的,所以这里主要是介绍ajax在前端中的操作.代码我省略的比较多,直接拿js那里的 $.ajaxFileUpload({ url:'www.cod ...

  7. angular 兼容ie7 实现

    <script src="~/Content/js/angular.min.js"></script><script src="~/Cont ...

  8. EasyUI-Datagrid 中formatter和group-formatter的使用

    1.在表格属性设置函数那块写以下内容: groupFormatter:function(value,rows){ //这里可以看到每一条导入表格中的数据,可以返回group的总结值 }, column ...

  9. win 2012 修改盘符

           开始--运行   diskmgmt.msc    ........

  10. EnableViewState

    EnableViewState 系统默认的值为true,在传递状态值时就包括该控件: 为false,则传递状态值时则不包括它. 可以提高网络访问的速度. 某些控件是不需要接受用户的操作或只需要接受一次 ...