Google Code Prettify

[MVC]捆綁和縮小 (Bundling and Minification)

捆綁和縮小是 ASP.NET 4.5 中可以使用的兩種技術,可以改善請求加載時間。捆綁和縮小可以減少對服務器的請求數量並減少所請求資產(例如 CSS 和 JavaScript )的大小,從而縮短加載時間。

大多數當前主流瀏覽器將每個主機名同時連接限制為六個。這意味著在同時處理請求多於六個時,其他請求就會進行排隊。


捆綁

Bundling 是 ASP.NET 4.5 中的一項新功能,可以輕鬆地將多個文件合併或捆綁到一個文件中。您可以創建 CSS,JavaScript 和其他捆綁包。更少的文件意味著更少的 HTTP 請求,並且可以提高首頁加載性能。

縮小

Minification 對腳本或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 name="ContextForImage" type="String" />The image context.
    ///</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/, "")) }



控制捆綁和縮小

通過 在 Web.config 文件中的編譯元素設置 debug 屬性的值來啟用或禁用捆綁和縮小在以下 XML 中,設置為 true ,因此禁用捆綁和縮小。debug

<system.web>
    <compilation debug="true" />
    <!-- Lines removed for clarity. -->
</system.web>


要啟用捆綁和縮小,請將 debug設置為 “false”。您可以使用上的屬性覆蓋 Web.config 設置以下代碼啟用捆綁和縮小,並覆蓋 Web.config 文件中的任何設置EnableOptimizationsBundleTable

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

    // Code removed for clarity.
    BundleTable.EnableOptimizations = true;
}


注意
除非EnableOptimizationstrue或者Web.config文件中的編譯元素 中的debug屬性設置為,否則不會捆綁或縮小文件。此外,將不使用.min版本的文件,將選擇完整的調試版本。覆蓋Web.config文件中編譯元素 中的debug屬性falseEnableOptimizations




使用ASP.NET MVC捆綁和縮小

在本節中,我們將創建一個ASP.NET MVC項目來檢查捆綁和縮小。首先,創建一個名為MvcBM的新ASP.NET MVC Internet項目,而不更改任何默認值。
打開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包,它包含Scripts文件夾中與通配符字符串“〜/ Scripts / jquery- {version”匹配的所有相應的(即調試或縮小但不是.vsdoc)文件。} .js文件“。對於ASP.NET MVC 4,這意味著使用調試配置,文件jquery-1.7.1.js將添加到包中。在發布配置中,將添加jquery-1.7.1.min.js捆綁框架遵循幾個常見的約定,例如:
  • FileX.min.jsFileX.js存在時,選擇“.min”文件以供發布
  • 選擇非“.min”版本進行調試。
  • 忽略僅由IntelliSense使用的“-vsdoc”文件(例如jquery-1.7.1-vsdoc.js)。
{version}上面顯示通配符匹配用於在Scripts文件夾中使用適當版本的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 = "https://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.
}

在上面的代碼中,將在發布模式下從CDN請求jQuery,並且將在調試模式下本地獲取jQuery的調試版本。使用CDN時,如果CDN請求失敗,您應該有一個回退機制。佈局文件末尾的以下標記片段顯示在CDN失敗時添加到請求jQuery的腳本。


</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提供方法來添加所有目錄中的匹配的搜索圖案,其中的文件(和任選的所有子目錄)。捆綁IncludeDirectoryAPI如下所示:


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方法在視圖中引用Bundles(Styles.Render對於CSS和Scripts.RenderJavaScript)。Views \ Shared \ _Layout.cshtml文件中的以下標記顯示了默認的ASP.NET Internet項目視圖如何引用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>

請注意,Render方法採用一個字符串數組,因此您可以在一行代碼中添加多個包。您通常希望使用Render方法創建必要的HTML來引用資產。您可以使用該Url方法生成資產的URL,而無需引用資產所需的標記。假設您要使用新的HTML5 異步屬性。以下代碼顯示瞭如何使用該Url方法引用modernizr 


<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方法可以選擇搜索子目錄。

捆綁緩存

捆綁包從創建捆綁包的一年開始設置 HTTP Expires Header 。如果您導航到以前查看的頁面,Fiddler 會顯示 IE 不會對該包發出條件請求,也就是說,沒有來自 IE 的捆綁包的 HTTP GET 請求,也沒有來自服務器的 HTTP 304 響應。您可以強制 IE 使用 F5 鍵為每個包發出條件請求(導致每個包的 HTTP 304 響應)。您可以使用^ F5強制完全刷新(導致每個包的 HTTP 200 響應。)

LESS,CoffeeScript,SCSS,Sass Bundling。

捆綁和縮小框架提供了一種處理SCSSSassLESSCoffeescript等中間語言的機制,並將縮小等變換應用於生成的捆綁包。例如,要將.less文件添加到MVC 4項目中:
      1.為您的LESS內容創建一個文件夾。以下示例使用Content \ MyLess文件夾。
      2.將.less NuGet包添加到您的項目無點。
NuGet dotless安裝

     3.添加一個實現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";
    }
}

     4.使用
LessTransformCssMinify轉換創建一個LESS文件包下面的代碼添加到RegisterBundles該方法應用\ _Start \ BundleConfig.cs文件。



var lessBundle = new Bundle("~/My/Less").IncludeDirectory("~/My", "*.less");
lessBundle.Transforms.Add(new LessTransform());
lessBundle.Transforms.Add(new CssMinify());
bundles.Add(lessBundle);

     5.將以下代碼添加到引用LESS包的任何視圖中。


@Styles.Render("~/My/Less");


捆綁注意事項

創建捆綁包時要遵循的一個好習慣是在捆綁包名稱中包含“bundle”作為前綴。這將防止可能的路由衝突
更新捆綁包中的一個文件後,將為捆綁包查詢字符串參數生成新令牌,並且下次客戶端請求包含捆綁包的頁面時,必須下載完整捆綁包。在傳統標記中,每個資產都單獨列出,只會下載更改的文件。經常變化的資產可能不適合捆綁。
捆綁和縮小主要改善首頁請求加載時間。一旦請求了網頁,瀏覽器就會緩存資產(JavaScript,CSS和圖像),因此在請求相同頁面或請求相同資產的同一網站上的頁面時,捆綁和縮小不會提供任何性能提升。如果未在資產上正確設置expires標頭,並且未使用捆綁和縮小,則瀏覽器新鮮度啟發式將在幾天后將資產標記為失效,並且瀏覽器將要求對每個資產進行驗證請求。在這種情況下,捆綁和縮小可在第一頁請求後提高性能。有關詳細信息,請參閱博客使用CDN和過期以提高網站性能
可以通過使用CDN來減輕每個主機名的六個同時連接的瀏覽器限制由於CDN將具有與您的託管站點不同的主機名,因此來自CDN的資產請求將不會計入對您的託管環境的六個同時連接限制。CDN還可以提供通用的包緩存和邊緣緩存優勢。
捆綁包應該由需要它們的頁面分區。例如,Internet應用程序的默認ASP.NET MVC模板創建了一個獨立於jQuery的jQuery Validation包。由於創建的默認視圖沒有輸入且不發布值,因此它們不包括驗證包。
System.Web.Optimization命名空間中實現System.Web.Optimization.dll它利用WebGrease庫(WebGrease.dll)進行縮小功能,後者又使用Antlr3.Runtime.dll