2012年11月27日 星期二

ASP.Net MVC中的Bundle

image

    ASP.Net MVC在第四版提供了一個貼心的工具-Bundle。而這個工具對於所有網頁開發的人員來說實在是一個至關重要的工具。一個網站除了功能和畫面UI能夠做到吸引人之外,更重要的地方就是網站要能夠讓更多人能夠瀏覽,否則再好的內容若總是只能幾隻小貓進來看,那豈不是太可惜了呢。

     影響一個網站能否讓更多人瀏覽有幾個重點:
  • 功能符合時下大眾需求
  • 畫面能夠第一時間吸引人
  • 友善的操作介面
  • 提供流暢的操作體驗而不會有頓感

    上述的每項牽涉的層面都非常廣泛,但是和今天要介紹的Bundle最息息相關的就屬第四項。網站要能夠提供流暢的操作體驗而不會讓使用者有頓感,其實就是在控制頁面響應能力;當使用者進入網頁或是點選某一個選單功能,結果就看到網頁凍結在那邊等著網站的回應,我想任何使用者都會逐漸感到不耐進而不想再繼續瀏覽下去。具所有開發人員的認知,一個頁面的響應時間不應該超過4秒,但是老實說這個4秒其實對於使用者來說是最大能夠忍受的極限,因此,不能將4秒作為網站響應時間的最終目標,而是應該將其作為危險指標。

     控制網頁響應時間的因素有很多,我大約羅列如下:
  • 後端/前端 程式沒有妥善控制資源(例如沒有關閉SqlConnection或無窮迴圈)
  • 沒有檢查好網站資源(例如使用者端向伺服器端要一張不存在的圖片)
  • 網頁太肥
  • 單一頁面需要向伺服器端索取多個資源檔

    在上述的因素中,其中的最後一項正是Bundle可以減緩的,為什麼只說可以減緩呢?因為Bundle僅能對於網站的JavaScript及CSS檔案做出處理,它的實際作用就是將網站上一堆的JavaScript或是CSS都打包成單一*.js或是*.css檔,如此一來,使用者端就不用開多個連線向伺服器端索取一堆的JavaScript以及CSS檔案了。這在某個程度上可以減緩索取多個資源檔所造成的連線損耗。

    使用者端發出一個Request給伺服器端,伺服器端在接收到這個Request之後,它會需要有一個執行緒去處理這個Request,為什麼要使用執行緒呢?這是因為網站本身的目的就是要能夠在同一時間盡可能的服務多個使用者的Request,為了達成這個目的,使用執行緒是勢在必行。其實,一台伺服器的執行緒個數是有限的,因為一個執行緒是會消耗掉近2MB的記憶體,而硬體資源不可能無限大但是使用者的數量卻可能無限上綱,為了能夠盡可能的服務多個使用者的Request,妥善的控制連線數也成了一個重要的課題。

     MVC 4所提供的Bundle的功能旨在打包JavaScript和CSS,除此之外,它還有一項更迷人的功能-壓縮。
    這裡所指的壓縮是指將原本很龐大的內容藉由將空白字元以及換行字元消滅掉之外,它還將JavaScript中的變數名稱替換成更簡單的a,b,c,d…這種單一字母,這是因為當字數越少則這個檔案相對來說就會更小,如此一來就做到了所謂實質上的壓縮功能。

    除了上述所探討到的執行緒問題之外,頻寬也是一個重要的指標,但是頻寬可能涉及到的層面很廣,除了JavaScript和CSS之外,當然免不了還有網頁的大小以及網頁上其它資源檔的大小,這些都是影響頻寬的因素,而Bundle不是萬靈丹,它僅能針對它能控制的JavaScript和CSS檔案的大小作文章之外,其餘部份它是愛莫能助的。

    接下來我們來看看App_Start資料夾底下的BundleConfig.cs檔案簡略內容:

    public class BundleConfig
    {
        // 如需 Bundling 的詳細資訊,請造訪 http://go.microsoft.com/fwlink/?LinkId=254725
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

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

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.unobtrusive*",
                        "~/Scripts/jquery.validate*"));

            // 使用開發版本的 Modernizr 進行開發並學習。然後,當您
            // 準備好實際執行時,請使用 http://modernizr.com 上的建置工具,只選擇您需要的測試。
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));

            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"));
        }
    }
   上述程式碼我們可以摸索出一個簡單的處理模式;當你想要針對JavaScript進行打包的時候,你只需要將ScriptBundle物件實體化並加入到bundles物件中,而CSS檔案則是將StyleBundle物件加入到bundles中。唯一幾個比較特別的程式碼如下:

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));
        在上述程式碼中我們可以看到有一個很醒目的東西: {version}。其實這個東西是一個特別的參數,而這是Bundle制定的,該參數的意思是指任何版本。jQuery是一個非常好用且熱門的JavaScript框架套件,以目前的網頁開發來說,不論是網頁設計師或是後端網站的程式設計師,皆要對這個框架套件非常熟才行,在過去,會jQuery是一件令人稱羨的事,而現在會jQuery卻成了必備的技能。jQuery從開始到現在已經有多個版本問世,如果每更新一次jQuery的新版就要去修改BundleConfig.cs,那豈不是太累人了,為此,便提供了像是{version}這種參數讓大家可以更方便的使用Bundle功能。

        更多的Bundle參數可以在這個網址中找到資源。

       我們現在就打開IE並且按下F12啟動檢測工具來看看Bundle的成效。

image

    咦!怎麼好像還是跑到原路徑去抓CSS和JavaScript檔案呢?其實,Bundle這項功能的啟動時機非常特別,它只有在非Debug模式下才能啟用,如果沒有改成非Debug模式,則Bundle則是毫無作用的。其目的很簡單,當你處於Debug模式時,表示你目前正在對該網站進行偵錯,而偵錯的目標很可能是某個自己撰寫的JavaScript,若這個檔案被Bundle壓縮的你完全看不懂,那要如何偵錯呢?

     接下來我們來將網站改成非Debug模式

image

    除了將原本的Debug改成Release之外,還要去修改網站的Web.config。(不是Views資料夾底下的那個歐)

<compilation debug="false" targetFramework="4.5"/>

   我們再來看一次網頁。(不偵錯啟動要按下: Ctrl+F5)

image

總結: Bundle是一個非常重要的功能,在MVC 4中,它的撰寫異常的簡單,為了這份簡單大家記得一定要去善用它歐。

1 則留言:

  1. Web.config 修改debug="false"
    著實解決了我爬文已久的問題 謝謝!!

    回覆刪除