ASP.NET MVC - ScriptBundle與StyleBuldle虛擬路徑命名問題

網頁程式設計師都知道在HTML Page裡如果需要使用外部的Javascript或Css樣式時就要引入,引用方式為加入<script src="..."></script>和<link ref="stylesheet" href="...">,但如果我一個Page要引入一堆script或link這樣不就要加到死,而且當我script或link的檔案位置有修改,那有引入該script或link的Page就要一個一個改,這實在太麻煩了。

ASP.Net MVC提供了一種Bundle機制,可以將相關的script或Css Bundle在一起,並為此Bundle命名,有用到的Page只要Load這一個Bundle就OK了,當檔案路徑有更動時,只要更改Bundle中的檔案路徑,所有相關的Page就會一次更改。

但今天限量要談的重點不是使用Bundle的詳細用法,而是使用Bundle時需要密切注意的一個設定項目,就是設定Bundle的虛擬路徑。

BundleConfig.cs
public class BundleConfig
{
    // 如需「搭配」的詳細資訊,請瀏覽 http://go.microsoft.com/fwlink/?LinkId=301862
    public static void RegisterBundles( BundleCollection bundles )
    {
        bundles.Add( new ScriptBundle( "~/bundles/jquery" ).Include(
            "~/Scripts/jquery-{version}.js" ) );

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

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

 bundles.Add( new ScriptBundle( "~/bundles/bootstrap" ).Include(
     "~/Scripts/bootstrap.js",
     "~/Scripts/respond.js" ) );

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

 // 將 EnableOptimizations 設為 false 以進行偵錯。如需詳細資訊,
 // 請造訪 http://go.microsoft.com/fwlink/?LinkId=301862
     BundleTable.EnableOptimizations = true;
    }
}

上面的程式碼是建立ASP.Net MVC專案後自動產生的BundleConfig,上面預設有4個ScriptBundle與1個StyleBundle,像"~/Content/css"就是一個StyleBundle虛擬路徑,這個虛擬路徑裡包含了"~/Content/"目錄下的bootstrap.csssite.css。以上在執行時是沒有問題的,接著來看看限量發現有問題的範例:




上面的虛擬路徑看似沒問題,但執行後會出現錯誤,整個CSS樣式都沒載進來。




這個錯誤的原因是因為"~/Content/metro-ui/css"已經有實體路徑了,所以會造成衝突。接著限量就把StyleBundle的虛擬路徑修改成"~/styles/metro-ui/css"。


這樣想說問題應該解了,但其實問題只解了一半,因為最後執行結果雖然CSS樣式有跑出來,但載入字型時竟然發生錯誤。


看到沒,在實體路徑上竟然會是用我設定的虛擬路徑去找。這原因是因為在metro-bootstrap.css裡有載入上層目錄裡font資料夾內的所有字型檔案,所以用虛擬路徑找就會GG了。在下面的參考來源中,限量找到的解法裡,作者說明"the bundle's virtual path match the actual directory in which the resources reside",就是虛擬路徑要和實體路徑相對應,這樣裡面的Resource才會找的到。根據作者的解答,限量將StyleBundle虛擬路徑修改成"~/Content/metro-ui/css/MetroUI""~/Content/metro-ui/css/"為實體路徑,MetroUI為Bundle的名稱,結果執行就OK了。









參考來源:
ASP.NET MVC 4 Fundamentals - ASP.NET, MVC, StyleBundle, ScriptBundle, BundleCollection




留言