ASP.NET MVC - ASP.NET MVC 4 Bundling and Minification

26 February 2012 — Written by Sky Chang
#ASP.NET#ASP.NET MVC#CSS#HTML#JavaScript#jQuery

2012/11/18 更新 - 這篇文章內容是舊版本,但概念上是相同的,大家也可以去黑暗大的這篇文章觀看,新舊的差異,主要是設定的方法有點不一樣。

從ASP.NET MVC或是ASP.NET的未來走向來看,我們可以看到,越來越多的功能,其實目的都是為了Mobile平台上的開發,當然,這塊也不是啥未來願景了,而是已經在發生的現在進行式;無論是朋友,同事,我想大家手機一拿出來,大概不外乎就是iPhone、Android、Win Phone,如果朋友拿出來的不是智慧手機,大概還會被大家噓一番XDD。

Bundling and Minification ( 綑綁與微小!? XD )

這個新的ASP.NET MVC 4 和 ASP.NET 4.5的新功能,也是為了Mobile而來,簡單的說,就是因為現在大家都用手機上網,看網站,但是好死不死,無線3G的頻寬又只有那麼一丁點,如果要下載許多資料頁面,就又卡在那邊,所以這次推出了這個新技術。

JavaScript & CSS

JavaScript和CSS已經可以說是網頁三巨頭的兩魔頭了,早期可能也只有CSS,但是,現在JavaScript和CSS再加上HTML,大概已經無法分離了;基本上,網頁的下載,HTML還好,因為不管怎樣,一個頁面,只會要求一次,但是JavaScript和CSS,可能就會因為設計得太好,切分得太漂亮,所以瀏覽器會和Server要求很多次( 因為有許多的JavaScript和CSS要下載 ),至於我,大概就沒有這種困擾吧XDDD,因為我都塞在同一個檔案阿!! ( 這是不好的行為喔 )

例如下面這段,我們要載入一堆的JavaScript。

<script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/_references.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/AjaxLogin.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout-2.0.0.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/modernizr-2.0.6-development-only.js")" type="text/javascript"></script>

這樣可能就會消耗掉463KB的頻寬

image

Bundling

Bundling這個新功能,他主要的目的,是希望可以把這些一次又一次的請求結合起來,變成只發送一次的請求,並且一次把所有的JavaScript ( or CSS )包回來,所以瀏覽器就少了很多次的要求,並且降低了傳輸的時間,所以的確有符合綑綁的意味喔!!

Minification

微小,我想大家應該也猜到了,就是縮小檔案;原理是將JavaScript的空白、註解、和不需要的文字給移除掉,以利檔案的傳輸,因為檔案大小更小了!

例如這一個超級簡單到爆炸的JavaScript

//Test
function Test() {
    alert("Test");
}

如果正常的情況下,我們可以看到在瀏覽器的偵錯模式下,顯示的是這樣。

image

但如果打開Minification,就會變成這樣,註解、和空白都不見了。

image

結果!

如果我們開啟Bundling and Minification,則只會消耗326KB。( 嗯,圖有點小,請見諒=w= )。

image

而根據官方說法,Bundling and Minification分別可以有20%和40%的提升,在某些網路不好的地方( 例如說台灣的行動上網 ),這可以大大的提高使用者開啟網頁的處理速度,當然,這部份也有一些小缺點和優點,缺點我想大家都很清楚,有時開發網頁的時候,會去用瀏覽器的除錯工具去看,有沒有哪些CSS、或是JavaScript沒被載下來,或是哪些是不需要載下來的,但如果全部Bundling,就沒辦法看到了QQ,其次,我想最頭痛的就是除錯;這樣沒註解沒空白的JavaScript,可能會要人命吧;但反之,這說不定是個簡易的混淆器XDD,總之,如果有良好的開發環境與架構,我想,這些都不算是問題吧。

如何用勒!?

如前面所說,如果今天是要掛一堆JavaScript,我想原始的方法大家應該都知道了,而如果要啟動這個Bundling and Minification,則需要這樣做。

首先,在Gloab.asax檔案下面,要加入BundleTable.Bundles.EnableDefaultBundles();,如果原本有BundleTable.Bundles.RegisterTemplateBundles();請先註解掉。

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    BundleTable.Bundles.EnableDefaultBundles();
    //BundleTable.Bundles.RegisterTemplateBundles();
}

( 這裡查到說BundleTable.Bundles.RegisterTemplateBundles();是預設樣板用的,所以也沒辦法改變目錄位置,所以網路上,人家說要改用BundleTable.Bundles.EnableDefaultBundles();至於是不是Bug,這部分可能也還要看原始碼,或是等正式版出了的時候,再做確定。 )

接下來,只要在原本的位址上,加上這兩行,就可以了;但要注意一下,下面的Url目錄的地方(例如~/Content/css),並非是Content底下css目錄。而是代表著Content底下的所有css檔案,同樣的,Script/js,也是代表著Script底下的js檔案,這個部分要注意一下。

<link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/css")" rel="stylesheet" type="text/css" />
<script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Scripts/js")"></script>

所以當Server看到這行,ASP.NET就會掃描目錄,並且Bundling and Minification。並且回覆給瀏覽器單一的響應,我們也不需要特別處理怎樣的步驟,也通通相容瀏覽器。

順序

基本上,包起來的JavaScript,會依據英文字母的順序包裝,或許大家第一個想到的就是,那如果有一個a.js,裡面用到jQuery.js,不就一定會錯了嗎?還好,雖然會依據英文字母順序,但如果是著名的Library,系統會自動幫忙排序,也就是說,他一定會把jQuery.js放到第一個,然後才會是a.js。

至於css的順序,其實也是一樣,像是著名的歸零css,reset.css,也會排在第一個。( 就是會把div等等標籤的margin、padding先預設為零的css )。

當然,這個順序也可以自訂。

終了

最後,這篇文章的內容是我邊看ScottGu大神的Blog,邊翻的,有興趣的也可以直接參考底下的參考連結;而這個機制,就如小弟我一開始說的,未來Mobile已經非常明確,而Mobile的資源有限,所以各大廠也提供許多的方法來支援,但不管怎樣,有用多的工具,有越多的彈性,總是好的,也希望這篇文章能帶來一些幫助。

參考資料

Sky & Study4.TW