Asp.Net MVC 捆綁(Bundle)

JoeSnail發表於2017-11-28

Asp.Net MVC 捆綁(Bundle)

大多數瀏覽器會對同一域名的請求限制請求數量,一般是在8個以內。每次最多可以同時請求8個,要是資源多於8個,那麼剩下的就要排隊等待請求了。所以為了提高首次載入頁面的速度。提高請求併發請求數量,降低請求次數就是一個很重要的點。

Bundle

Asp.Net MVC4和.NET Framework4.5提供了支援捆綁和壓縮的新類庫System.Web.Optimization

該類庫提供瞭如下特性:

  • 捆綁-將多個資原始檔(javascript,css)合併成一個單獨的檔案,但是合併成的單獨檔案必須是相同型別,要麼都是JavaScript要麼都是CSS。
  • 壓縮資原始檔-清理空格,換行等,壓縮檔案大小。
  • 自動清理快取-服務端更新資源時,客戶端不再使用快取資源,而是重新從服務端快取。

1. 定義Bundle

App_Start檔案中新增一個BundleConfig.cs檔案。實現靜態RegisterBundles方法。該方法用來建立,註冊和配置bundle。(在該目錄下程式碼最好把他們的名稱空間去掉 ".App_Start",保持一個統一的高等級的名稱空間)。

  • 呼叫BundleCollection.Add()方法新增捆綁資源,該方法引數為ScriptBundleStyleBundle

  • ScriptBundleStyleBundle需要傳遞一個虛擬路徑給建構函式。該虛擬路徑其實就是該捆綁的名稱或者識別符號。所以該虛擬路徑可以任意設定,並不需要匹配物理路徑。BundleInclude方法包含一個或者多個指令碼。

  • 通過引用該虛擬路徑就可以使用這些捆綁的資源@Script.Render("~/bundles/jquery")

  • Debug模式下預設沒有開啟捆綁和壓縮,釋出模式下預設是開啟的。

public static void RegisterBundles(BundleCollection bundles)
{
     //該值為true,在任何模式下都使用捆綁和壓縮。
     //BundleTable.EnableOptimizations = true;
     
     //新增名稱為“~/bundles/jquery”指令碼捆綁
     bundles.Add(new ScriptBundle("~/bundles/jquery").Include("~/Scripts/jquery-{version}.js"));
     //新增名稱為“~/Content/css”樣式捆綁
     bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/Site.css"));
}

使用{version}佔位符可以在使用NuGet更新Jquery版本時,不需要更新Bundle的引用,自動使用最新的Jquery版本。

ScriptBundleStyleBundleInclude方法引數是一個字串型別的陣列,所以一個Bundle例項可以新增多個檔案。

bundles.Add(new StyleBundle("~/Content/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"));

但是Bundle類也提供了IncludeDirectory方法,可以新增指定目錄下的指定檔案。

//新增Content/themes/base目錄下的所有css檔案
bundles.Add(new StyleBundle("~/Content/css"").IncludeDirectory("~/Content/themes/base", "*.css"));

使用萬用字元要注意:

  • 使用萬用字元新增資源時。這些資原始檔是按照名稱來排序的。

2. 啟用Bundle

在Global.asax的Appliaction_Start方法中呼叫之前的定義的方法,BundleConfig.RegisterBundles(BundleTable.Bundles)
啟用Bundle。

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

3. 使用Bundle

如果我們需要在頁面中使用這些資源時。可以通過Styles和Scripts來引入。如果要使用捆綁的Style,可以在頁面中新增@Styles.Render("~/Content/css")。如果要使用捆綁的Script,可以在頁面中新增@Script.Render("~/bundles/jquery")

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - 我的 ASP.NET 應用程式</title>
    //引入樣式捆綁
    @Styles.Render("~/Content/css")    
</head>
<body>    
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - 我的 ASP.NET 應用程式</p>
        </footer>
    </div>
    //引入js捆綁
    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
</body>
</html>

可以把CSS樣式檔案置頂,JavaScript檔案置底,來優化網頁。但是modernizr.js檔案要放在頁面頂部,因為有些樣式檔案需要。


使用CDN

Bundle對CDN也提供了很好的支援。

public static void RegisterBundles(BundleCollection bundles)
{
    //bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
    //            "~/Scripts/jquery-{version}.js"));

    bundles.UseCdn = true;   //啟用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"));
}

在使用CDN時,要應對沒有獲取到資源的情況。


        @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>   

Bundle快取

瀏覽器是根據URL來快取資料的。瀏覽器無論何時請求資源,都會根據URL來檢查快取裡是否包含了該資原始檔。如果包含了,瀏覽器就不會再去請求,而是使用快取的檔案,來渲染。

Bundle機制使我們每次修改資原始檔時都會在URL後自動新增一個雜湊值,從而避免瀏覽器快取,不能及時更新資源的情況。

Asp.Net MVC 捆綁(Bundle)

v=******,後面的值就是雜湊值。Bundle 在Debug模式下預設是沒有開啟的。在釋出模式下才會開啟。但是我們可以在BundleConfig下新增BundleTable.EnableOptimizations = true;開啟捆綁模式。


Bundle注意事項

  • 一個Bundle一般包含多個檔案,如果我們只是修改了其中的一個檔案,那麼Bundle的雜湊值也會改變,就會更新Bundle的所有檔案。

  • 捆綁和縮小主要降低了第一次訪問頁面時載入的時間。此時靜態資源就會被快取起來(js,css,圖片)。當訪問其他頁面,且該頁面的資源地址和第一次訪問的地址相同時,就會從快取裡獲取,不再向服務端獲取。

  • 如果資源過多,使用CDN,比使用Bundle更有效。當然Bundle也可以結合CDN使用。 通過使用CDN,可以減輕每個主機名8個併發連線的瀏覽器限制。因為CDN的主機名與您的主機站點不同,CDN上的資產請求不會與您的主機環境的8個併發連線數計數。

  • Bundle最好按照功能來區分捆綁。例如,預設的ASP.Net應用程式的NET MVC模板建立了一個與jQuery分離的jQuery驗證包。因為所建立的預設檢視輸入輸出值,所以它們需要驗證包。


如有不對,請多多指教。


參考:

相關文章