我试图渲染一堆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会按照相同的顺序将它们渲染出来.
更新默认排序
Bundling使用IBundleOrderer的概念对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(); } }
所以默认的orderer实际上是一个DefaultBundleOrderer,直到你用自定义的orderer覆盖它.
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很容易覆盖,所以它对给定的文件集没有任何影响,因此顺序仍然是原始的.