捆绑(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. 详细解释 集成Maven Spring Mybatis项目包生成Bat文件

    有时在项目必须Maven项目包生成bat文件,长官一人.本文将解释的具体使用方法maven-assembly-plugin插件实现bat文件包. 1.首先看一下项目结构 2.配置pom.xml文件,在 ...

  2. java Json字符串转List<Map>类型

    //相关包 import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonPa ...

  3. LinkedBlockingQueue多线程测试

    public class FillQueueThread extends Thread { private Queue queue; public FillQueueThread(Queue queu ...

  4. ORACLE查看和更改的最大连接数

     第一步,在cmd命令行,进入sqlplus 第二步骤,根据提示输入username与password 1. 视图processes和sessions参数 SQL> show paramet ...

  5. AngularJS 疑难问题解决汇总

    AngularJS 防止页面闪烁的方法 angularjs filter 详解 学习资料1 学习资料2 在 AngularJS 应用中处理单选框和复选框 学习资料3 AngularJS 之 Facto ...

  6. HDU 3523 Image copy detection(KM最大匹配)

    HDU 3523 Image copy detection 题目链接 题意:这题事实上题意读懂就简单了,说白了就是1-n放到1-n列,每列的值为每列上数字和该数字的差的绝对值,然后求总和最小 思路:就 ...

  7. my97 日期控件

    官网:http://www.my97.net/   好多广告啊! 文档地址: http://www.mysuc.com/test/My97DatePicker/

  8. 关于重写ID3 Algorithm Based On MapReduceV1/C++/Streaming的一些心得体会

    心血来潮,同时想用C++连连手.面对如火如荼的MP,一阵念头闪过,如果把一些ML领域的玩意整合到MP里面是不是很有意思 确实很有意思,可惜mahout来高深,我也看不懂.干脆自动动手丰衣足食,加上自己 ...

  9. NET 2015

    .NET 2015 英文原文:Understanding .NET 2015 Understanding 翻译为了解或理解,对于 .NET 来说,2015 年注定会更加精彩,所以标题就用了“精彩”这个 ...

  10. 日期格式化{0:yyyy-MM-dd HH:mm:ss.fff}和{0:yyyy-MM-dd hh:mm:ss.fff}的区别

    原文:日期格式化{0:yyyy-MM-dd HH:mm:ss.fff}和{0:yyyy-MM-dd hh:mm:ss.fff}的区别 {0:yyyy-MM-dd HH:mm:ss.fff}:使用24小 ...