[ASP.NET] Bundling Script and Style 加速網站效能

介紹使用綑綁壓縮 Script 與 Style,使用 Bundling 加速網站效能

前言


在 Visual Studio 2013 的預設 WebFrom 模板下可以看到使用綑綁(Bundle)的方式載入 Script.js 與 Style.css 檔案,使用這個綑綁的方式有什麼好處呢? 

 

System.Web.Optimization 命空間是在 .NET 4.5 推出,內容提供了 CDN、JavaScript、CSS 優化、綑綁與壓縮處理的類別,參考 Bundling and Minification 此文的介紹,為什麼要使用 Bundle ? 使用 Bundle 可以將數個 .js 或 .css 檔案綑綁成一個檔案,在瀏覽器發送 Request 的狀況下一般會限制同一時間發出的 Request 數量,當網站的 script 與 css 檔案很多時,將會依照限制數量分批進行下載 script 與 css 檔案至客戶端。

 

例如下圖所示

 

理所當然,當網站內需要載入的檔案越多就必須經過更多的等候時間才能讓檔案下載完成,所以使用綑綁的功用就在於可以將多個 script 與 style 檔案綑成同一個檔案,讓瀏覽器能夠透過 1 或 2 個 Request 就將原本可能 10 多個的 script 與 style 檔案下載至客戶端。並且在綑綁的過程中,也會將所綑綁的 script 與 style 檔案進行壓縮。

 

壓縮的方式就如下圖所示

壓縮前的回應

壓縮後的回應

 

經過壓縮的動作,會將原本包含換行、空白、註解的部分去除而降低檔案的大小。

接下來就來看看實作方式。

 

在網站加入 Bundling 


首先必須在網站中加入 Web.Optimization 套件,使用 NuGet 進行安裝即可,如下圖所示

 

安裝完成後在 App_Code 下增加一個 BundleConfig 類別,內容如下


public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        // bundling script.
        bundles.Add(
            new ScriptBundle("~/bundles/scripts")
            .Include(
                "~/Scripts/Script1.js",
                "~/Scripts/Script2.js",
                "~/Scripts/Script3.js",
                "~/Scripts/Script4.js"            
            ));

        // bundling styles.
        bundles.Add(
            new StyleBundle("~/bundles/styles")
            .Include(
                "~/Styles/Style1.css",
                "~/Styles/Style2.css",
                "~/Styles/Style3.css",
                "~/Styles/Style4.css"
            ));
    }
}

 

ScriptBundle 與 StyleBundle 分別是使用於 Script.js 與 Style.css 的綑綁,傳入的引數為自訂虛擬路徑,在透過 Include 方法傳入需要綑綁的檔案路徑,當要綑綁多個檔案的時候用逗號區隔即可。

 

BundleConfig 類別完成後就需要去註冊這個綑綁方法,在網站加入 全域應用程式類別(Global.asax) 並在 Application_Start 方法中註冊 BundleConfig,如下,記得要 Import System.Web.Optimization Namespace


void Application_Start(object sender, EventArgs e) 
{
    // 在應用程式啟動時執行的程式碼
    
    // 註冊綑綁
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

 

接著需要到 Web.Config 檔案中加入一條組態設定,如下,如此才能夠在 .aspx 頁面識別之後的 Scripts.Render 方法。


<system.web>
  <pages>
    <namespaces>
      <add namespace="System.Web.Optimization" />
    </namespaces>
  </pages>
</system.web>

 

以上前置動作都完成後,就可以到 .aspx 撰寫輸出的語法了,在 .aspx 頁面如果要指定輸出哪一個 Bundle 檔案的話,可以使用 Scripts.Render 或 Styles.Render 方法,引數傳入當初設定的虛擬路徑即可,如下


<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <%: Styles.Render("~/bundles/styles") %>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:PlaceHolder runat="server">
            <%: Scripts.Render("~/bundles/scripts") %>
        </asp:PlaceHolder>
    </div>
    </form>
</body>
</html>

 

如果想在 Code Behind 再來控制輸出的檔案,可以使用以下方式


protected void Page_Init(object sender, EventArgs e)
{
    Literal literal = new Literal();
    literal.Text = Styles.Render("~/bundles/styles").ToHtmlString();
    Header.Controls.Add(literal);
}

 

完成後測試一下 Script 與 Style 檔案是否順利輸出,如下

 

這時可以發現檔案的確是順利輸出在 HTML 的標籤內,但是一定會有一個疑問? 看起來跟沒綑綁一樣啊? 說好的綑綁呢?

其實綑綁的啟用時機是在 Web.Config 的 Debug 屬性設定為 false 的情況下才會執行,所以修改 Web.Config 的 Debug 屬性為 false 後重新執行,如下

 

發送的 Request 也減少到兩個了,無需等待

 

以上就是透過綑綁的對網站進行效能優化的方式,另外若碰到某些特殊情況 Style 的圖片不會顯示時,可以使用 Include(string virtualPath,params IItemTransform[] transforms) 方法重寫路徑,如下


bundles.Add(
    new StyleBundle("~/bundles/styles2")
    .Include("~/Styles/Style1.css", new CssRewriteUrlTransform()));

 

補充


2016.01.12
針對 CSS 檔案進行 Bundle 後的圖片路徑問題,可以參考此篇文章處理 [ASP.NET] TypeScript + AngularJs 使用 ASP.NET Bundle 與自動判斷載入 JS

 

範例程式碼


TBundles.rar

 

參考資料


Bundling and Minification

System.Web.Optimization Namespace

CssRewriteUrlTransform Class

 

 


以上文章敘述如有錯誤及觀念不正確,請不吝嗇指教
如有侵權內容也請您與我反應~謝謝您 :)