打包(Bundling)及壓縮(Minification)指的是將多個js文件或css文件打包成單一文件並壓縮的作法,如此可減小瀏覽器需下載多個文件案才能完成網頁顯示的延遲感,同時經過移除JS/CSS文件案中空白、批註及修改JavaScript內部函數、變量名稱的壓縮手法,能有效縮小文件案體積,提升傳輸效率,提供使用者更流暢的瀏覽體驗。javascript
在ASP.NET MVC 4中能夠使用BundleTable捆綁多個css文件和js文件,以提升網絡加載速度和頁面解析速度。更爲重要的是經過捆綁能夠解決IE瀏覽器的31個CSS文件鏈接的限制。在作ASP.Net項目時不少時候會使用一些開源的javascript控件。無形中增長了css和javascript文件的引用。若是手工將這些css文件合併將給未來版本升級形成很大的麻煩。因而,咱們只好當心翼翼的處理這些css文件在頁面中的引用。ASP.NET捆綁是ASP.NET 4.5的新功能,是System.Web.Optimization命名空間下。他提供了一些ASP.NET運行性能方面的優化,好比,一個頁面可能有不少CSS/JS/圖片,經過靈活的應用BundleTable類,他能夠幫你將文件合併壓縮代碼優化成一個最理想的文件,而後輸出到客戶端,從而提升了瀏覽器下載速度。css
如今咱們終於有一個以相對比較完美的解決方案來解決css文件和javascirpt文件給咱們帶來的麻煩,BundleTable捆綁技術很好的解決了這個問題。html
在ASP.NET MVC 4 Beta時代便已內建打包壓縮功能,作法是在global.asax.cs的Application_Start加入java
BundleTable.Bundles.EnableDefaultBundles();jquery
如此,即可使用如下寫法一口氣將整個Scripts目錄下的JS及Contents目錄下全部CSS打包並壓縮成單一文件案,改善網頁載入效率: (參考)ajax
<script src="@Url.Content("~/Scripts/js")" type="text/javascript"></script>
<script src="@Url.Content("~/Content/CSS")" type="text/javascript"></script>瀏覽器
最近在看ASP.NET MVC 4 RC,發現RC版在打包壓縮作法上又有所革新,變得更加彈性有條理。網絡
本來打包規則被藏在global.asax.cs Application_Start中,RC版起則多了一個新目錄App_Start,其中包含RouteConfig.cs、FilterConfig.cs、BundleConfig.cs三個類,作法上改成經過WebActivator啓動。新的系統配置將路由規則、過濾器及打包規則等註冊邏輯由Application_Start中拆出來,各自放在獨立文件案中,管理及修改起來一目瞭然,架構上更漂亮。架構
BundleConfig.cs的預設內容以下:mvc
using System.Web;
using System.Web.Optimization;
namespace MyMvcApplicaiton
{
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-1.*"));
bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
"~/Scripts/jquery-ui*"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.unobtrusive*",
"~/Scripts/jquery.validate*"));
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));
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"));
}
}
}
跟Beta時代很大的差別是將JS與CSS加以羣組化,分別定義出jquery, jqueryui, jqueryval, modernizr, css及themes/base/css等羣組,讓網頁能夠視須要只加載必要的JS及CSS文件羣組,不像先前每次得打包整個目錄,對於JS文件的加載順序及相依性也能作較精準的調控。
而在.cshtml中,則使用Styles.Render及Scripts.Render載入BundleConfig.cs所定義的JS及CSS羣組,例如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/themes/base/css", "~/Content/css")
@Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/bundles/jquery", "~/bundles/jqueryui",
"~/bundles/jqueryval")
@RenderSection("scripts", required: false)
</head>
<body>
@RenderBody()
</body>
</html>
接着來實測一下,作一個簡單的Index.cshtml,中間只有<div>Hello</div>一行,配合上述的_Layout.cshtml,進行測試,沒想到呈現的源代碼以下,一個個CSS及JS文件都是分開的,沒打包也沒壓縮?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title></title>
<link href="/Content/themes/base/jquery.ui.core.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/jquery.ui.resizable.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/jquery.ui.selectable.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/jquery.ui.accordion.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/jquery.ui.autocomplete.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/jquery.ui.button.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/jquery.ui.dialog.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/jquery.ui.slider.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/jquery.ui.tabs.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/jquery.ui.datepicker.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/jquery.ui.progressbar.css" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/jquery.ui.theme.css" rel="stylesheet" type="text/css" />
<link href="/Content/site.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/modernizr-2.0.6-development-only.js" type="text/javascript"></script>
<script src="/Scripts/jquery-1.6.2.js" type="text/javascript"></script>
<script src="/Scripts/jquery-ui-1.8.11.js" type="text/javascript"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>
</head>
<body>
<div>Hello</div>
</body>
</html>
原來,這也是ScriptBundle及StyleBundle的貼心之處,在調試模式下,會展示CSS及JS原貌,方便開發人員檢查源代碼找問題與除錯。要見識它的打包壓縮效果,記得要設定<compilation debug="false" targetFramework="4.0" />。
關閉調試模式後,網頁的源代碼就變成如下的樣子,一個羣組只有一個<link>或<script>,而href及src會指向/Content/css?v=ji3nXsakWko…(包含哈希碼參數,以確保文件案變更時只會載入新版)格式的連結,傳回多個文件案打包及壓縮後的內容:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title></title>
<link href="/Content/themes/base/css?v=UM62...略" rel="stylesheet" type="text/css" />
<link href="/Content/css?v=ji3n...略" rel="stylesheet" type="text/css" />
<script src="/bundles/modernizr?v=XGaE...略" type="text/javascript"></script>
<script src="/bundles/jquery?v=3AwA...略" type="text/javascript"></script>
<script src="/bundles/jqueryui?v=bMdf...略" type="text/javascript"></script>
<script src="/bundles/jqueryval?v=uFE7...略" type="text/javascript"></script>
</head>
<body>
<div>Hello</div>
</body>
</html>
最後,實際測量兩者的性能差異:
在未打包壓縮前,加載網頁須要發出20個請求,總共傳輸5,992+812,541=818,533 Bytes的資料。
打包壓縮後,請求數降低到7個,數據傳輸量也減小爲2,274+352,454=354,728 Bytes,數據傳輸量只有本來的43.33%!
在開發ASP.NET MVC 4項目時,不要忘記這個有用的機制。
最後介紹一個System.Web.Optimization的擴展庫 http://bundletransformer.codeplex.com/,推薦在ASP.NET MVC 4項目中使用。
http://www.codeproject.com/Articles/395143/JavascriptHelper-Managing-JS-files-for-ASP-NET-MVC