MVC4 StyleBundle 沒有以正確的順序呈現包
我正在嘗試渲染一組 css 文件,但輸出順序錯誤。我已經嘗試了解決方案@ MVC4 Beta Minification and Bundling: Ordering files and debugging in browser,但沒有幫助。這是捆綁包:
bundles.Add(new StyleBundle("~/stylesheet") .Include("~/css/main.css") .Include("~/css/mvc.css") .Include("~/js/jquery.thickbox.css") .Include("~/js/jquery.rating.css") .Include("~/css/ProductListing.css") .Include("~/css/dropdown/dropdown.css") .Include("~/css/dropdown/dropdown.vertical.css") .Include("~/js/fancybox/jquery.fancybox-1.3.1.css") .Include("~/css/scartpopup.css") .Include("~/css/ShoppingCart.css") .Include("~/css/ceebox.css") .Include("~/css/tooltip.css") .Include("~/css/recent_blog_posts.css") .Include("~/css/ProductDetail.css") .Include("~/css/jquery-ui-1.7.3.custom.css") .Include("~/css/filter_box.css") .Include("~/css/custom_page.css") .Include("~/css/Checkout.css") .Include("~/css/CheckoutButton.css") );這是結果,您可以看到 jquery-ui 排在首位。
<link href="/css/jquery-ui-1.7.3.custom.css" rel="stylesheet"/> <link href="/css/main.css" rel="stylesheet"/> <link href="/css/mvc.css" rel="stylesheet"/> <link href="/js/jquery.thickbox.css" rel="stylesheet"/> <link href="/js/jquery.rating.css" rel="stylesheet"/> <link href="/css/ProductListing.css" rel="stylesheet"/> <link href="/css/dropdown/dropdown.css" rel="stylesheet"/> <link href="/css/dropdown/dropdown.vertical.css" rel="stylesheet"/> <link href="/js/fancybox/jquery.fancybox-1.3.1.css" rel="stylesheet"/> <link href="/css/scartpopup.css" rel="stylesheet"/> <link href="/css/ShoppingCart.css" rel="stylesheet"/> <link href="/css/ceebox.css" rel="stylesheet"/> <link href="/css/tooltip.css" rel="stylesheet"/> <link href="/css/recent_blog_posts.css" rel="stylesheet"/> <link href="/css/ProductDetail.css" rel="stylesheet"/> <link href="/css/filter_box.css" rel="stylesheet"/> <link href="/css/custom_page.css" rel="stylesheet"/> <link href="/css/Checkout.css" rel="stylesheet"/> <link href="/css/CheckoutButton.css" rel="stylesheet"/>如何確保樣式表以正確的順序呈現?
捆綁不應該以完全相同的順序呈現 CSS 文件,它遵循不同的邏輯。如果您需要按定義呈現它們,那麼您應該創建一個自定義IBundleOrderer並將其設置為所需的 Orderer:
public class AsDefinedBundleOrderer : IBundleOrderer { public IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) { return files; } }和
var bundle = new StyleBundle("~/stylesheet"); bundle.Orderer = new AsDefinedBundleOrderer(); bundles.Add(bundle);然後這將不會對列表執行任何操作,因此 Render 將以完全相同的順序呈現它們。
更新預設排序
捆綁使用的概念對
IBundleOrderera 中的項目進行排序Bundle。該類Bundle具有Orderer如下所示的屬性:public IBundleOrderer Orderer { get { if (this._orderer == null) return (IBundleOrderer) DefaultBundleOrderer.Instance; else return this._orderer; } set { this._orderer = value; this.InvalidateCacheEntries(); } }因此,預設排序器實際上是 a
DefaultBundleOrderer,直到您用自定義排序器覆蓋它。具有以下
IBundleOrderer簽名:public interface IBundleOrderer { IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files); }這個的
DefaultBundleOrderer實現按 對文件進行BundleContext排序,這裡是實現的一個片段OrderFiles:foreach (BundleFileSetOrdering ordering in (IEnumerable<BundleFileSetOrdering>) context.BundleCollection.FileSetOrderList) DefaultBundleOrderer.AddOrderingFiles(ordering, (IEnumerable<FileInfo>) list, fileMap, foundFiles, result);所以不同的結果會因為這個而發生。這當然不是隨機排序算法 :) 規則在
BUndleCollection類中定義:public static void AddDefaultFileOrderings(IList<BundleFileSetOrdering> list) { if (list == null) throw new ArgumentNullException("list"); BundleFileSetOrdering bundleFileSetOrdering1 = new BundleFileSetOrdering("css"); bundleFileSetOrdering1.Files.Add("reset.css"); bundleFileSetOrdering1.Files.Add("normalize.css"); list.Add(bundleFileSetOrdering1); BundleFileSetOrdering bundleFileSetOrdering2 = new BundleFileSetOrdering("jquery"); bundleFileSetOrdering2.Files.Add("jquery.js"); bundleFileSetOrdering2.Files.Add("jquery-min.js"); bundleFileSetOrdering2.Files.Add("jquery-*"); bundleFileSetOrdering2.Files.Add("jquery-ui*"); bundleFileSetOrdering2.Files.Add("jquery.ui*"); bundleFileSetOrdering2.Files.Add("jquery.unobtrusive*"); bundleFileSetOrdering2.Files.Add("jquery.validate*"); list.Add(bundleFileSetOrdering2); BundleFileSetOrdering bundleFileSetOrdering3 = new BundleFileSetOrdering("modernizr"); bundleFileSetOrdering3.Files.Add("modernizr-*"); list.Add(bundleFileSetOrdering3); BundleFileSetOrdering bundleFileSetOrdering4 = new BundleFileSetOrdering("dojo"); bundleFileSetOrdering4.Files.Add("dojo.*"); list.Add(bundleFileSetOrdering4); BundleFileSetOrdering bundleFileSetOrdering5 = new BundleFileSetOrdering("moo"); bundleFileSetOrdering5.Files.Add("mootools-core*"); bundleFileSetOrdering5.Files.Add("mootools-*"); list.Add(bundleFileSetOrdering5); BundleFileSetOrdering bundleFileSetOrdering6 = new BundleFileSetOrdering("prototype"); bundleFileSetOrdering6.Files.Add("prototype.js"); bundleFileSetOrdering6.Files.Add("prototype-*"); bundleFileSetOrdering6.Files.Add("scriptaculous-*"); list.Add(bundleFileSetOrdering6); BundleFileSetOrdering bundleFileSetOrdering7 = new BundleFileSetOrdering("ext"); bundleFileSetOrdering7.Files.Add("ext.js"); bundleFileSetOrdering7.Files.Add("ext-*"); list.Add(bundleFileSetOrdering7); }因此,當您從以下位置呼叫時
Application_Start:BundleConfig.RegisterBundles(BundleTable.Bundles);實際上,您傳遞
BundleCollection了庫中定義的預設值。因此,我們將
BundleFileSetOrdering實例一一傳遞到:private static void AddOrderingFiles(BundleFileSetOrdering ordering, IEnumerable<FileInfo> files, Dictionary<string, HashSet<FileInfo>> fileMap, HashSet<FileInfo> foundFiles, List<FileInfo> result) { foreach (string key in (IEnumerable<string>) ordering.Files) { if (key.EndsWith("*", StringComparison.OrdinalIgnoreCase)) { string str = key.Substring(0, key.Length - 1); foreach (FileInfo fileInfo in files) { if (!foundFiles.Contains(fileInfo) && fileInfo.Name.StartsWith(str, StringComparison.OrdinalIgnoreCase)) { result.Add(fileInfo); foundFiles.Add(fileInfo); } } } else if (fileMap.ContainsKey(key)) { List<FileInfo> list = new List<FileInfo>((IEnumerable<FileInfo>) fileMap[key]); list.Sort((IComparer<FileInfo>) FileInfoComparer.Instance); foreach (FileInfo fileInfo in list) { if (!foundFiles.Contains(fileInfo)) { result.Add(fileInfo); foundFiles.Add(fileInfo); } } } } }結論
如果我們想簡化這個過程,我們可以說庫更喜歡某種文件,如果找到多種可能性,則對其他文件進行一些排序。這是大多數情況下的預期行為,但正如您所見,它很容易被覆蓋,
AsDefinedBundleOrderer因此它對給定的文件集不執行任何操作,因此順序保持原始順序。