Asp.net-Mvc-4

MVC4 StyleBundle 沒有以正確的順序呈現包

  • June 28, 2021

我正在嘗試渲染一組 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因此它對給定的文件集不執行任何操作,因此順序保持原始順序。

引用自:https://stackoverflow.com/questions/14775997