捆绑和缩小是两种方法可用于在 ASP.NET 4.5 改进请求加载时间。捆绑和缩小提高加载时间减少到服务器的请求数和减小大小的要求资产 (如 CSS 和 JavaScript。)
当前主流浏览器的大多数限制的每个主机名到六每个并发连接数。这意味着虽然正在处理六个请求,将由浏览器排队资产在主机上的其他请求。在下面的图像中,IE F12 开发人员工具网络选项卡显示资产由关于视图的一个示例应用程序所需的时间。
灰色条显示该请求排队等待的六个连接限制,浏览器的时间。黄色栏是请求到第一个字节的时间就是发送请求和接收来自服务器的第一反应所需的时间。蓝色条形显示从服务器接收的响应数据所需的时间。您可以双击资产以获得详细的计时信息。例如,下面的图像显示加载/Scripts/MyScripts/JavaScript6.js文件的计时详细信息。
前面的图像显示的启动的事件,使时间要求被排队因为浏览器的限制同时连接的数量。在这种情况下,请求被排队等待另一个请求完成 46 毫秒为单位)。
捆绑销售
捆绑销售是 ASP.NET 4.5 使它容易地合并,或将多个文件捆绑到单个文件中的新功能。您可以创建 CSS、 JavaScript 和其他包。较少的文件意味着更少的 HTTP 请求和,可以改善第一页负载性能。
下面的图像显示显示以前,但这次与捆绑和缩小启用的关于视图的同一时间视图。
缩小
缩小执行各种不同的代码优化和脚本或 css,如删除不必要的空白和注释和缩短到一个字符的变量名。考虑下面的 JavaScript 函数。
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 |
捆绑的影响和缩小
下表显示了几个重要的区别,分别列出所有资产和使用中的示例程序的捆绑和缩小 (B/M) 之间。
| 使用 B/M | 没有 B/M | 变化 |
文件请求 | 9 | 34 | 256% |
发送的 KB | 3.26 | 11.92 | 266% |
收到 KB | 388.51 | 530 | 36% |
加载时间 | 510 MS | 780 MS | 53% |
发送的字节数有显著减少与捆绑浏览器相当详细与它们适用的请求的 HTTP 标头。接收字节数减少不是一样大的因为最大的文件 (Scripts\jquery-ui-1.8.11.min.js和Scripts\jquery-1.7.1.min.js) 都已经模糊不清。注意: 在示例程序上的计时使用提琴手工具来模拟较慢的网络。(从提琴手规则菜单中,选择性能然后模拟调制解调器速度.)
调试捆绑和缩减 JavaScript
很容易调试您在开发环境中的 JavaScript (在编译元素 在Web.config文件设置为debug="true"
你也可以调试发布版本哪里您 JavaScript 文件捆绑在一起,并且模糊不清。您使用 IE F12 开发人员工具,调试使用以下方法最包中包含的 JavaScript 函数:
- 脚本选项卡,然后选择启动调试按钮。
- 选择包含您想要使用的资产按钮进行调试的 JavaScript 函数的捆绑。
- 通过选择配置按钮设置最的 JavaScript 的格式然后选择格式 JavaScript.
- 在搜索以股代息t 输入框中,选择您想要调试的函数的名称。在下面的图像中,搜索以股代息t 输入框中输入了AddAltToImg
F12 开发人员工具调试的详细信息,请参阅 MSDN 文章:使用 F12 开发人员工具调试 JavaScript 错误.
控制捆绑和缩小
启用或禁用通过在编译元素中设置的调试属性的值绑定和缩小 的Web.config文件中。在下面的 XML,debug
设置为 true,那么将捆绑和缩小处于禁用状态。
<system.web>
<compilation debug="true" />
<!-- Lines removed for clarity. -->
</system.web>
要启用捆绑和缩小,设置为"false"的debug
值。您可以重写Web.config设置与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;
}
注: 除非EnableOptimizations
是true
或编译元素中的调试属性 在Web.config文件设置为false
,将不捆绑或文件模糊不清。此外,将不使用的文件的.min 版本,将选择的完整的调试版本。EnableOptimizations
重写汇编元素中的调试属性 的Web.config文件中
使用捆绑和缩小与 ASP.NET Web 窗体和 Web 页
- Web 页,请参阅博客条目添加到 Web 页站点的网站优化.
- 有关 Web 窗体,请参阅博客添加捆绑和缩小到 Web 窗体.
使用捆绑与 ASP.NET MVC 放缩法
在这一节我们将创建 ASP.NET MVC 项目,审查捆绑和缩小。首先,创建一个新的 ASP.NET MVC 互联网项目,命名为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 束 (这是调试或模糊不清但不是。vsdoc) 在脚本文件夹中的文件相匹配的通配符字符串"~/Scripts/jquery-{版本}.js"。对于 ASP.NET MVC 4,这意味着调试配置中,文件jquery 1.7.1.js将被添加到包。在发布配置, jquery 1.7.1.min.js将被添加。捆绑框架如以下几个共同的约定:
- 时存在"FileX.min.js"和"FileX.js",请选择".min"版本文件中。
- 选择用于调试的非".min"版本。
- 忽略"-vsdoc"仅使用智能感知的文件 (如 jquery-1.7.1-vsdoc.js)。
如上所示的{version}
通配符匹配用于自动创建一个 jQuery 束具有适当版本的 jQuery脚本文件夹中。在此示例中,使用通配符提供了以下好处:
- 允许您使用 NuGet 更新到新的 jQuery 版本而无需更改前面的绑定代码或 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.
}
在上面的代码中,jQuery 将请求从 CDN 虽然在释放模式和 jQuery 的调试版本将被回迁本地在调试模式下。当使用 CDN,你应该有一个回退机制在 CDN 请求失败的情况下。下面的标记片段从布局文件的末尾显示脚本添加请求 jQuery 应 CDN 失败。
</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>
创建包
包类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"));
提供包类IncludeDirectory
方法,以添加一个目录中的所有文件 (和 (可选) 与搜索模式匹配的所有子目录)。包类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 方法中,(对 CSS Styles.Render
) 和Scripts.Render
的 JavaScript 来引用的捆绑包。从Views\Shared\_Layout.cshtml文件下面的标记显示默认 ASP.NET 互联网项目视图如何引用 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>
请注意渲染方法采用字符串数组,因此您可以在一行代码中添加多个软件包。你一般会想要使用所创建的必要的 HTML 来引用该资产的渲染方法。您可以使用 Url
方法生成的 URL,该资产,而引用该资产所需的标记。假设你想要使用新的 HTML5 async属性。下面的代码演示如何引用 modernizr 使用Url
的方法。
<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
下表显示的文件添加到捆绑使用通配符,如图所示:
电话 | 添加文件或引发异常 |
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实现,但显式添加每个文件都少出错,可以降低这种风险。例如,您可能会添加新的资产到文件夹在将来可能会要求您修改您的IBundleOrderer实现。
- 查看特定文件添加到使用通配符加载目录可以包含在引用该捆绑包的所有视图。如果查看特定脚本添加到包中,你可能会引用捆绑其他视图上一个 JavaScript 错误。
- 将其他文件导入的 CSS 文件导致两次加载导入的文件。例如,下面的代码创建一个束与大多数的 jQuery UI 的主题 CSS 文件加载两次。
bundles.Add(new StyleBundle("~/jQueryUI/themes/baseAll")
.IncludeDirectory("~/Content/themes/base", "*.css"));
- 在每个 CSS 文件夹中的文件,包括Content\themes\base\jquery.ui.all.css文件带来的通配符"*.css"选择器。Jquery.ui.all.css文件中导入其他 CSS 文件。
捆绑缓存
捆绑组 HTTP Expires 标题从捆绑在创建时的一年。如果您导航到以前查看过的页面,提琴手显示 IE 不会捆绑包,有条件的请求就是有 IE 捆绑,没有 HTTP GET 请求,并没有来自服务器的 HTTP 304 响应。您可以强制 IE,使每个包的条件请求使用 F5 键 (导致每个包的 HTTP 304 响应)。您可以通过使用强制完全刷新 ^ F5 (导致每个包的 HTTP 200 响应)。
缓存选项卡的提琴手响应窗格中:
请求
http://localhost/MvcBM_time/bundles/AllMyScripts?v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81用于AllMyScripts捆绑并包含一个查询字符串对v = r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81。查询字符串v有一个令牌就是一个唯一的标识符,用于缓存的值。只要该捆绑不发生变化,ASP.NET 应用程序会要求使用此令牌的AllMyScripts捆绑。如果在包中的任何文件发生更改,ASP.NET 优化框架将生成新的令牌,保证浏览器请求捆绑包将得到最新捆绑。
如果您运行的 IE9 F12 开发人员工具,并导航到以前加载的页面,IE 不正确地显示每个包和服务器返回 HTTP 304 作出的有条件 GET 请求。您可以阅读为什么 IE9 已确定如果使用 Cdn 和改进 Web 站点的性能对过期的博客条目中做了一个有条件的请求的问题.
较少,CoffeeScript、 SCSS,敢亵渎捆绑销售。
捆绑和缩小框架提供一种机制来处理中间语言如SCSS、上海社会科学院、较少或Coffeescript,并适用于产生捆绑的转换,如缩小。例如,要将.less文件添加到您的 MVC 4 项目:
- 创建一个文件夹为您较少的内容。下面的示例使用Content\MyLess文件夹。
- 添加.less NuGet 包拉丁文到您的项目。
- 添加一个类实现IBundleTransform接口。.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";
}
}
- 创建与
LessTransform
- 和CssMinify变换较少的文件包。将下面的代码添加到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);
- 将下面的代码添加到引用的少捆绑的任何视图。
@Styles.Render("~/My/Less");
捆绑软件注意事项
创建包时遵循良好公约 》 是包括"捆绑"作为软件包名称中的前缀。这将防止路由冲突的可能.
一旦您更新包中的一个文件,为捆绑查询字符串参数生成一个新的令牌和充分的捆绑必须下载一个客户端请求的页面包含包的下一次。在传统标记中的每个资产所单独列,仅更改后的文件将被下载。频繁更改的资产捆绑可能不到很好的候选。
捆绑和缩小主要改善的第一页请求加载时间。一旦请求了一个网页,浏览器会缓存 (JavaScript、 CSS 和图像) 的资产所以捆绑和缩小在请求同一页面时,不会提供任何性能提升或页面上相同站点请求同一资产。如果不设置过期标头正确地对您的资产,您不使用捆绑和缩小,浏览器新鲜度试探法将标志着资产陈旧几天后和浏览器的每个资产的需要验证请求。在这种情况下,捆绑和缩小后的第一个页面请求提供性能提高。有关详细信息,请参阅博客使用 Cdn 和过期的改进 Web 站点的性能.
通过使用CDN可以降低浏览器限制的每个主机名每六个同时连接。因为 CDN 将比您承载的网站有一个不同的主机名,从 CDN 资产请求不会计算针对六个同时连接数限制到您的宿主环境。CDN 也可以提供共同包缓存和缓存优势的边缘。
束应由页需要它们进行分区。例如,默认的 internet 应用程序的 ASP.NET MVC 模板创建 jQuery 验证包单独从 jQuery。因为创建的默认视图有没有输入,并且不发布值,它们不包含验证包。
System.Web.Optimization
命名空间是在 System.Web.Optimization.DLL 中实现的。它利用了 WebGrease 库 (WebGrease.dll) 对于缩小功能,它反过来使用 Antlr3.Runtime.dll。