demoshop

demo, trying to be the best_

這篇主要是詳細說明筆者在 twMVC#8 時所介紹的「靜態檔案最佳化」其中的一個內建工具應用,也補齊一些《ASP.NET MVC4 網站開發美學》中沒有提到的部分。先特別強調此功能內建在 ASP.NET MVC4 中,並且是利用 NuGet 在持續維護與更新,所以本文的內容可能一段時間以後就不正確了,觀看時請務必注意版本資訊。

筆者無法在這裡詳細說明前端網頁效能瓶頸的點在哪裡,所以有寫一篇前置文章【線上測速工具 WebPagetest 馬上得知網站效能瓶頸】利用工具簡單快速的讓前端開發人員瞭解目前網站的瓶頸,不過對於完全沒有前端網頁最佳化相關知識的朋友,可能會不瞭解這樣做的意義。因此推薦《高效能網站建置指南 (Even Faster Web Sites: Performance Best Practices for Web Developers)》這本很有名的書籍,雖然內容有極少部分不太適合現在網頁的新技術,但大多數的觀念與技巧還是相當受用,有興趣的朋友可以購買觀看。


注意事項

  1. 最佳化與打包 js 和 css 檔案至少可以達到前端網站優化中的「Make fewer HTTP requests」「Minify JS」兩個規則。
  2. 本文章需要使用 ASP.NET MVC4 才可正確執行。
  3. 最佳化後的JS或CSS可能不正常,上線前務必完整測試。
  4. 範例檔案請點選上方的【主要下載】字樣

開始進入正題...

在 ASP.NET MVC 4中新增了「App_Start」資料夾,其中有一個「BundleConfig.cs」類別就是設定整個最佳化和打包的設定檔。


再修改設定檔之前先要瞭解為什麼程式有能力將獨立載入的檔案包成一包,請讀者點開範例檔案中的「Views\Shared\_Layout.cshtml」可以看到載入 CSS 與 JS 的方式是使用了 HTML Helper 的方式,因此才有打包的能力。

(ASP.NET MVC4 預設的範例也是使用 CSS 放上 JS 放下的網站最佳化原則)


回到「BundleConfig.cs」。各位讀者將「BundleConfig.cs」開啟後可以看到在筆者已經再內容中設定了很多組載入範例


版本範例解說

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
            "~/Scripts/jquery-{version}.js"));

利用了 {version} 變數,可以載入不限定版本的檔案,如下圖所示

注意事項眼尖的讀者可能會發現 jQuery 同時載入兩個版本,這是使用 Version 的一個需要注意的點,如果專案中有多個符合條件的都會一併載入,切記不要讓專案內有不正確的檔案。


萬用字元範例解說

#region 萬用字元
bundles.Add(new ScriptBundle("~/bundles/TEST").Include(
            "~/Scripts/fakejs-1*"));
            //使用萬用字元設定只要 1.*

bundles.Add(new ScriptBundle("~/bundles/TEST").Include(
            "~/Scripts/fakejs-2*"));
            //使用萬用字元設定只要 2.*
#endregion

許多套件都會有版本相容的問題,以 jQuery 做範例,jQuery 1.8 版與 jQuery 1.9 版就不是相容的,如果讀者使用了上面介紹的版本載入方式,可能會不小心載入過新的版本而導致系統異常,要避免這情況可以考慮使用 * 萬用字元,利用萬用字元就可以明確的指定到主版本,例如使用 jquery.1.8* 的方式就不會載入主版號超過 1.8 的檔案,但是 1.8.1 、1.8.2、1.8.3 這種小更新還是可以正常載入。


載入目錄範例解說

#region 載入目錄
bundles.Add(new ScriptBundle("~/bundles/TEST").IncludeDirectory(
            "~/Scripts/", "test*", true));
//載入 Scripts 目錄下所有前置為test的 js
#endregion

如果讀者的專案有使用目錄整理得很乾淨,就可以考慮使用載入目錄的方式載入檔案,依據上方指令翻成白話文來說就是,載入 Scripts 目錄下所有前置為 test 的檔案,並且搜尋所有子目錄(後方的 true 表示是否搜尋子目錄)。

注意事項如果專案檔案沒有整理得很好,建議還是逐一指定,不要使用載入目錄的方式。


CDN支援範例解說

#region CDN支援
//開啟 CDN
bundles.UseCdn = true;
//設定 CDN 目錄
var jqueryCdnPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js";
//優先載入 CDN 位置,如 CDN 失效將使用本機位置提供資源
bundles.Add(new ScriptBundle("~/bundles/jquery",
            jqueryCdnPath).Include(
            "~/Scripts/jquery-{version}.js"));
#endregion

依據前端網頁優化的建議中,CDN也是一個很不錯的解決方案,此工具也支援了CDN的使用,利用這設定的好處為當 CDN 路徑無法正常讀取時,程式會立即轉換為本機的指定目錄提供資源,避免因為 CDN 的不穩定導致網站異常。


介紹到這裡先來緩一下,如果讀者有嘗試一步一步測試可能會發現在使用每種載入的方式好像都會遺漏檔案,其實這主要是因為內建的忽略清單定義所導致,預設情況下使用 Bundles 載入的檔案都自動忽略尾端帶有 min 的檔案,主要是避免二次最佳化導致程式錯誤,這內定忽略清單是可以自行定義的,如果他影響到你的使用習慣,可以自行調整。

 

自訂忽略清單範例解說

#region 自定忽略清單
bundles.Add(new ScriptBundle("~/bundles/jquery").IncludeDirectory(
            "~/Scripts/", "test*", true));
//載入 Scripts 目錄下所有前置為test的 js

bundles.IgnoreList.Clear();
bundles.IgnoreList.Ignore("*.min.js", OptimizationMode.WhenEnabled);
bundles.IgnoreList.Ignore("*-vsdoc.js");
bundles.IgnoreList.Ignore("*.debug.js", OptimizationMode.WhenEnabled);

#endregion

這段程式應該很清楚可以了解,這就不多提了,更詳細的資料可以參考MSDN文件【IgnoreList.Ignore Method (String, OptimizationMode) (System.Web.Optimization)


到這裡讀者可能會有各疑問,看到的明明就都是一個一個的檔案,並沒有所謂「最佳化」和「打包」的情況出現,這是因為此套機制在 Debug Mode 下並不會進行「最佳化」和「打包」方便開發者除錯,當程式變成 Release Mode 時才會進行「最佳化」和「打包」,現在開啟「Web.Config」將 Debug 設定成 false 重新編譯後執行網站就可以看到「最佳化」和「打包」的效果了。

然後你會發現所有的載入路徑後面都加上了v={亂碼}

這是為了避免瀏覽器快取所做的設計,會依據「壓縮」後的內容不同而產生不同的亂碼,這樣才可以確保,當內容改變後使用者可以抓取到新的檔案。

 

其餘內容可以參考《ASP.NET MVC4 網站開發美學

回應討論