捆绑(Bundle)

本文介绍 MVC 4 提供的一个新特性:捆绑(Bundle),一个在  View 和 Layout 中用于组织优化浏览器请求的 CSS 和 JavaScript 文件的技术。

本文目录

了解VS默认加入的脚本库

当我们创建一个基本模板的 MVC 工程时,VS在Scripts文件夹中默认加入了一些 JavaScript 脚本库。下面是这些脚本库的简单介绍:

  • jquery-1.8.2.js,这个就不用解释了。
  • jquery-ui-1.8.24.js,在jQuery 基础上的一套界面工具,包括了网页上常见的很多插件和动画特效。
  • jquery.validate.js,用于验证用户在表单内input元素输入的数据。
  • knockout-2.2.0.js,是一个轻量级的UI类库,通过应用MVVM模式使JavaScript前端UI简单化,更多:http://knockoutjs.com/documentation/introduction.html
  • modernizr-2.6.2.js,一个开源的JS库,它使得那些基于访客浏览器的不同(指对新标准支持性的差异)而开发不同级别体验的设计师的工作变得更为简单。它使得设计师可以在支持HTML5和CSS3的浏览器中充分利用HTML5和CSS3的特性进行开发,同时又不会牺牲其他不支持这些新技术的浏览器的控制。更多:http://www.mhtml5.com/2011/03/676.html 。
  • jquery.unobtrusive-ajax.js,MVC 框架中使用 Unobtrusive Ajax 的库,更多:[ASP.NET MVC 小牛之路]14 - Unobtrusive Ajax 。
  • jquery.validate.unobtrusive.js,基于 jquery.unobtrusive-ajax.js,更多:[ASP.NET MVC 小牛之路]15 - Model Binding 。

另外还有一个 _references.js 文件,它的作用是通过下面这种方式放入该文件中的JS文件可以被VS智能感知:

/// <reference path="jquery-1.8.2.js" />
/// <reference path="jquery-ui-1.8.24.js" />

相关小技巧:在VS中让一个JS文件智能提示另一个JS文件中的成员 。

在实际的项目中,我们可能远远不止引入上面这些脚本文件,MVC 4提供的“捆绑”新功能可以很方便地对引入的脚本文件进行管理。

准备工作

选择基本模板创建一个MVC工程。和前一篇的示例差不多,创建一个名为 Appointment 的 Model,代码如下:

 Appointment

添加一个 HomeController,代码如下:

 HomeController

给MakeBooking action添加一个 MakeBooking.cshtml 视图,代码如下:

@model MvcApplication1.Models.Appointment
@{
AjaxOptions ajaxOpts = new AjaxOptions {
OnSuccess = "processResponse"
};
}
<h4>Book an Appointment</h4> <script src="~/Scripts/Home/MakeBooking.js"></script> <div id="formDiv" class="visible">
@using (Ajax.BeginForm(ajaxOpts)) {
@Html.ValidationSummary(true)
<p>@Html.ValidationMessageFor(m => m.ClientName)</p>
<p>Your name: @Html.EditorFor(m => m.ClientName)</p>
<p>@Html.ValidationMessageFor(m => m.Date)</p>
<p>Appointment Date: @Html.EditorFor(m => m.Date)</p>
<p>@Html.ValidationMessageFor(m => m.TermsAccepted)</p>
<p>@Html.EditorFor(m => m.TermsAccepted) I accept the terms & conditions</p>
<input type="submit" value="Make Booking" />
}
</div>
<div id="successDiv" class="hidden">
<h4>Your appointment is confirmed</h4>
<p>Your name is: <b id="successClientName"></b></p>
<p>The date of your appointment is: <b id="successDate"></b></p>
<button id="backButton">Back</button>
</div>

把该视图需要的 JavaScript 代码放在一个单独的文件 MakeBooking.js 中,并将该JS文件放在 /Scripts/Home 文件夹下,该JS文件代码如下:

 MakeBooking.js

注意,这里需要对后台通过Json方法返回的日期进行处理,Json 方法返回的日期格式是:/Date(1385308800000)/,所以把它呈现给客户端时用 processDate JS方法处理了一下。

在 Content 文件夹下添加一个样式文件 CustomStyles.css,代码如下:

div.hidden { display: none;}
div.visible { display: block;}

最后清理一下 _Layout.cshtml 文件,如下:

 _Layout.cshtml

本文将关心的是 JS 和 CSS 文件的引用,大家不用关心代码本身,此时只需Copy好代码,一会使用捆绑让它运行起来。

使用捆绑管理脚本和样式文件

以前我们引入脚本和样式文件的时候,都是一个个的引用,看起来一大坨,不小心还会弄错先后次序,管理很是不便。而且很多脚本库有普通和 min 两个版本,开发的时候我们引入普通版本以方便调试,发布的时候又换成min版本以减少网络带宽,很是麻烦。为此,MVC 4 增加了一个新功能:“捆绑”,它的作用是把一类脚本或样式文件捆绑在一起,在需要用的时候调用一句代码就行,极大地方便了脚本和样式文件的管理;而且可以把脚本的普通和 min 两个版本都捆绑起来,MVC也会根据是否为Debug模式智能地选择脚本文件的版本。下面我们来看看这个捆绑功能的使用。

用捆绑方便之一是可以在 /App_Start/BundleConfig.cs 中通过注册来统一管理脚本和样式文件。我们可以打开 BundleConfig.cs 文件看看VS 已经默认对脚本和样式文件的捆绑情况。为了演示如何使用捆绑,我们把VS默认的捆绑代码删除,再增加我们需要的捆绑,如下所示:

public class BundleConfig {
public static void RegisterBundles(BundleCollection bundles) {
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/*.css")); bundles.Add(new ScriptBundle("~/bundles/clientfeaturesscripts").Include(
"~/Scripts/jquery-{version}.js",
"~/Scripts/jquery.validate.js",
"~/Scripts/jquery.validate.unobtrusive.js",
"~/Scripts/jquery.unobtrusive-ajax.js"));
}
}

捆绑是通过 RegisterBundles 参数对象的 Add 方法添加。Add 方法的参数需要一个ScriptBundle 类 或 StyleBundle 类的实例对象, 脚本文件用的是 ScriptBundle 类,样式文件用的是 StyleBundle 类,它们的构造参数代表着捆绑在一起的文件的引用。 Include 方法用于包含具体要捆绑的文件。其中的 {version} 是文件版本的占位符,MVC会在相应的目录下定位到最新的一个版本文件。

使用捆绑方便之二是再也不用引入一大坨的文件了,如下面的 _Layout.cshtml:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/css")
</head>
<body>
@Scripts.Render("~/bundles/clientfeaturesscripts")
@RenderBody()
</body>
</html>

这里通过 @Scripts.Render 和 @Styles.Render 两个Helper方法添加捆绑。需要注意的是,MakeBooking.cshtml 文件引入的 MakeBooking.js 是基于 jQuery的,所以 _Layout.cshtml的 @Scripts.Render("~/bundles/clientfeaturesscripts") 必须放在 @RenderBody() 之前。

使用脚本 Section

上面我们提到在 _Layout.cshtml 中,@Scripts.Render("~/bundles/clientfeaturesscripts") 必须放在 @RenderBody() 之前,因为View引入的JS是基本jQuery的。有时候由于某种需求或个人的喜好要把 @RenderBody() 放在 @Scripts.Render("~/bundles/clientfeaturesscripts") 之前,如果这样的话,MakeBooking.js 文件就在jQuery库之前引用了,显然JS会报错。

对于这种情况,我们可以用 [ASP.NET MVC 小牛之路]12 - Section、Partial View 和 Child Action 文章介绍的Section来解决这种JS引用次序的问题。如下,我们可以把 MakeBooking.cshtml 中引入JS的部分用section包起来:

...
<h4>Book an Appointment</h4>
@section scripts {
<script src="~/Scripts/Home/MakeBooking.js" type="text/javascript"></script>
}
...

然后我们就可以在 _Layout.cshtml 所有Render方法后面使用  @RenderSection("scripts", required: false) 方法引入MakeBooking.js 文件,这样就不用关心在 _Layout.cshtml 中的 @RenderBody() 和 @Scripts.Render("~/bundles/clientfeaturesscripts") 的先后次序了。如下所示:

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

这样保证了 MakeBooking.js 一定在jQuery库文件之后引用。

使用捆绑带来的改变

捆绑除了可以方便地管理脚本和样式文件,还可以给网络减少带宽。

以下是在Debug模式下使用捆绑MVC生成引用部分的代码:

<link href="/Content/CustomStyles.css" rel="stylesheet"/>
<link href="/Content/Site.css" rel="stylesheet"/>
...
<script src="/Scripts/jquery-1.8.2.js"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
...
<script src="/Scripts/Home/MakeBooking.js"></script>

总共 7 个文件,在Debug模式下使用捆绑和不使用捆绑没什么区别。

下面我们来比较一下在发布模式下不使用捆绑和使用捆绑两者使用带宽的情况。

在 Web.config 中把调式模式关闭,如下:

...
<system.web>
<httpRuntime targetFramework="4.5" />
<compilation debug="false" targetFramework="4.5" />
...

我们先来看看不使用捆绑使用带宽的情况,为此,我们 MakeBooking.cshtml 中的section部分 和 _Layout.cshtml 中的引用捆绑的部分注释掉。并在 _Layout.cshtml 中引入上面 7 个文件,如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@*@Styles.Render("~/Content/css")*@
<link href="~/Content/CustomStyles.css" rel="stylesheet"/>
<link href="~/Content/Site.css" rel="stylesheet" />
<script src="~/Scripts/jquery-1.8.2.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
<script src="~/Scripts/Home/MakeBooking.js"></script>
</head>
<body>
@RenderBody()
@*@Scripts.Render("~/bundles/clientfeaturesscripts")
@RenderSection("scripts", required: false)*@
</body>
</html>

运行程序,用IE F12 工具查看请求服务器资源的情况(注意要先清理缓存),结果如下:

我们看到在不使用捆绑的情况下,客户端接收的数据总大小为330.65 KB。

我们再来看看使用捆绑带宽的使用情况。我们把之前在 MakeBooking.cshtml 和 _Layout.cshtml 中的注释去掉,并把 _Layout.cshtml 引入 7 个文件的代码删除。

运行程序(注意清涂缓存),结果如下:

我们看到,使用捆绑客户端接收的数据总大小为 124.01 KB,和不使用捆绑相比少200多KB,即一半多,这是非常可观的。

我们也注意到,使用捆绑请求的链接也少了。这是因为在发布模式下,响应客户端请求时,MVC整合并最小化了JavaScript文件和样式文件,并使得一个捆绑中的内容在一个请求中加载。如果我们查看Html代码,可以看到 Styles.Render 和 Scripts.Render 两个方法生成了这样的HTML引用代码:

<link href="/Content/css?v=6jdfBoUlZKSHjUZCe_rkkh4S8jotNCGFD09DYm7kBWE1" rel="stylesheet"/>
...
<script src="/bundles/clientfeaturesscripts?v=KyclumLmAXQGM1-wDTwVUS31lpYigmXXR8HfERBGk_I1"></script>
..
<script src="/Scripts/Home/MakeBooking.js"></script>

一个Styles.Render 或 Scripts.Render 方法生成了一个带有v参数的URL,这个URL将使MVC把一整个捆绑的数据进行最小化处理并一次发送到客户端。


参考:《Pro ASP.NET MVC 4 4th Edition》

捆绑(Bundle)的更多相关文章

  1. [ASP.NET MVC 小牛之路]17 - 捆绑(Bundle)

    本文介绍 MVC 4 提供的一个新特性:捆绑(Bundle),一个在  View 和 Layout 中用于组织优化浏览器请求的 CSS 和 JavaScript 文件的技术. 本文目录 了解VS默认加 ...

  2. 自学MVC看这里——全网最全ASP.NET MVC 教程汇总

    MVC架构已深得人心,微软也不甘落后,推出了Asp.net MVC.小编特意整理博客园乃至整个网络最具价值的MVC技术原创文章,为想要学习ASP.NET MVC技术的学习者提供一个整合学习入口.本文从 ...

  3. ASP.NET MVC 教程汇总

    自学MVC看这里——全网最全ASP.NET MVC 教程汇总   MVC架构已深得人心,微软也不甘落后,推出了Asp.net MVC.小编特意整理博客园乃至整个网络最具价值的MVC技术原创文章,为想要 ...

  4. 全网最全ASP.NET MVC 教程汇总

    全网最全ASP.NET MVC 教程汇总 MVC架构已深得人心,微软也不甘落后,推出了Asp.net MVC.小编特意整理博客园乃至整个网络最具价值的MVC技术原创文章,为想要学习ASP.NET MV ...

  5. 自学MVC看这里——全网最全ASP.NET MVC 教程汇总(转)

    自学MVC看这里——全网最全ASP.NET MVC 教程汇总   MVC架构已深得人心,微软也不甘落后,推出了Asp.net MVC.小编特意整理博客园乃至整个网络最具价值的MVC技术原创文章,为想要 ...

  6. [Android Traffic] 看无线电波如何影响网络操作]

    转载自: http://blog.csdn.net/kesenhoo/article/details/7391031 Optimizing Downloads for Efficient Networ ...

  7. 自学MVC看这里——全网最全ASP.NET MVC 教程汇总【转】

    自学MVC看这里——全网最全ASP.NET MVC 教程汇总 http://www.cnblogs.com/powertoolsteam/archive/2015/08/13/4667892.html ...

  8. TCP/IP具体解释学习笔记——数据链路层(2)

    五 Wireless LANs(Wi-Fi) 现在很流行的一种接入互联网的方式就是Wi-Fi了.我们用的ipad.手机.笔记本电脑等等都能够用这样的方式接入互联网,很方便灵活.一个典型的Wi-Fi网络 ...

  9. [ASP.Net] 转 > ASP.NET MVC 小牛之路

    URL: http://www.cnblogs.com/willick/ 看到了不错的学习笔记,MVC.Net学习之路展开   [ASP.NET MVC 小牛之路]18 - Web API [ASP. ...

随机推荐

  1. 什么时候rootViewController至tabbarController时刻,控制屏幕旋转法

    于ios6后,ios系统改变了屏幕旋转的方法,假设您想将屏幕旋转法,在需求rootvc里面制备,例如 UIViewController *viewCtrl = [[UIViewController a ...

  2. 宽客的人&amp;&amp;事件映射

    看完<宽客>这本书,叙事介绍20世纪华尔街对冲基金.股票.投资者依赖股市从直觉交易数学家的早期演化.物理学家用数学模型开发过程中的交易,这些进入金融数学家.物理学家依靠大数据分析.稍纵即逝 ...

  3. Objective-C马路成魔【14-关键C语言功能】

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主.捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 这里介绍一 ...

  4. EF4.1: Add/Attach and Entity States(EF中的实体状态转换说明)

    实体的状态,连接以及 SaveChanges 方法 数据库上下文对象维护内存中的对象与数据库中数据行之间的同步.这些信息在调用 SaveChanges方法被调用的时候使用.例如,当使用 Add 方法传 ...

  5. 如何利用【百度地图API】,制作房产酒店地图?(下)——结合自己的数据库

    原文:如何利用[百度地图API],制作房产酒店地图?(下)--结合自己的数据库 摘要:应广大API爱好者要求,写了一篇利用自己数据库标点的文章…… -------------------------- ...

  6. ASP.NET MVC性能优化工具 MiniProfiler

    ASP.NET MVC性能优化工具 MiniProfiler 2014年04月19日 ⁄ ASP.NET ⁄ 共 1159字 ⁄ 字号 小 中 大 ⁄ 暂无评论 ⁄ 阅读 325 views 次 MV ...

  7. json.net 比jsonIgnore 更好的方法 修改源码

    关于 JsonIgnore  问题, EF T4 模板 中 存在主外键关系 namespace WindowsFormsApplication1{    using System;    using ...

  8. Yii Framework2.0开发教程(4)在yii中定义全局变量

    在yii中定义全局变量最好的地方是入口脚本处.也就是web目录中的index.php文件 比如我们在defined('YII_ENV') or define('YII_ENV', 'dev');后写上 ...

  9. Windows服务之启动、停止、暂停、继续

    原文:Windows服务之启动.停止.暂停.继续 Windows服务之启动.停止.暂停.继续 2011-11-09 15:07:37     我来说两句 收藏    我要投稿    [字体:小 大] ...

  10. jenkins综合cobertura,来电显示cobertura的report

    我的项目是使用maven作为构建工具.左右maven如何整合jenkins请参阅: http://blog.csdn.net/yaominhua/article/details/40684355 本文 ...