我如何指定一个显式的ScriptBundle包含顺序?
我正在尝试MVC4 System.Web.Optimization 1.0 ScriptBundlefunction 。
我有以下configuration:
public class BundleConfig { public static void RegisterBundles(BundleCollection bundles) { // shared scripts Bundle canvasScripts = new ScriptBundle(BundlePaths.CanvasScripts) .Include("~/Scripts/modernizr-*") .Include("~/Scripts/json2.js") .Include("~/Scripts/columnizer.js") .Include("~/Scripts/jquery.ui.message.min.js") .Include("~/Scripts/Shared/achievements.js") .Include("~/Scripts/Shared/canvas.js"); bundles.Add(canvasScripts); } }
和以下看法:
<script type="text/javascript" src="@Scripts.Url(BundlePaths.CanvasScripts)"></script>
BundlePaths.CanvasScripts
是"~/bundles/scripts/canvas"
。 它呈现这个:
<script type="text/javascript" src="/bundles/scripts/canvas?v=UTH3XqH0UXWjJzi-gtX03eU183BJNpFNg8anioG14_41"></script>
到目前为止这么好,除了~/Scripts/Shared/achievements.js
是捆绑源代码中的第一个脚本。 它依赖于ScriptBundle
之前包含的每个脚本。 我怎样才能确保它能够遵循我向包中添加include语句的顺序?
更新
这是一个相对较新的ASP.NET MVC 4应用程序,但它引用了优化框架预发布包。 我删除它,并从http://nuget.org/packages/Microsoft.AspNet.Web.Optimization添加RTM包。 使用web.config中的debug = true的RTM版本, @Scripts.Render("~/bundles/scripts/canvas")
以正确的顺序呈现各个脚本标记。
在web.config中debug = false的情况下,组合脚本首先具有这些plays.js脚本,但是由于它的函数定义(对象构造函数)稍后调用,所以它运行时没有错误。 也许这个缩小器足够聪明,能够发现依赖关系吗?
我也尝试了Darin Dimitrov用RTM和两个debugging选项build议的IBundleOrderer
实现,它的performance也一样。
所以缩小版本是不是我所期望的顺序,但它的工作原理。
我没有看到RTM位上的这种行为,您是否使用Microsoft ASP.NET Web Optimization Framework 1.0.0位: http : //nuget.org/packages/Microsoft.AspNet.Web.Optimization ?
我使用了一个类似的数据库,基于一个新的MVC4互联网应用程序网站。
我添加到BundleConfig.RegisterBundles:
Bundle canvasScripts = new ScriptBundle("~/bundles/scripts/canvas") .Include("~/Scripts/modernizr-*") .Include("~/Scripts/Shared/achievements.js") .Include("~/Scripts/Shared/canvas.js"); bundles.Add(canvasScripts);
然后在默认的索引页面中,我添加了:
<script src="@Scripts.Url("~/bundles/scripts/canvas")"></script>
而且我确认了在这个捆绑的缩小的JavaScript中,achievement.js的内容是在现代化之后…
您可以编写一个自定义绑定IBundleOrderer
者( IBundleOrderer
),以确保绑定包含在您注册的订单中:
public class AsIsBundleOrderer : IBundleOrderer { public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) { return files; } }
接着:
public class BundleConfig { public static void RegisterBundles(BundleCollection bundles) { var bundle = new Bundle("~/bundles/scripts/canvas"); bundle.Orderer = new AsIsBundleOrderer(); bundle .Include("~/Scripts/modernizr-*") .Include("~/Scripts/json2.js") .Include("~/Scripts/columnizer.js") .Include("~/Scripts/jquery.ui.message.min.js") .Include("~/Scripts/Shared/achievements.js") .Include("~/Scripts/Shared/canvas.js"); bundles.Add(bundle); } }
并在你看来:
@Scripts.Render("~/bundles/scripts/canvas")
谢谢达林。 我已经添加了一个扩展方法。
internal class AsIsBundleOrderer : IBundleOrderer { public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) { return files; } } internal static class BundleExtensions { public static Bundle ForceOrdered(this Bundle sb) { sb.Orderer = new AsIsBundleOrderer(); return sb; } }
用法
bundles.Add(new ScriptBundle("~/bundles/jquery").Include( "~/Scripts/jquery-{version}.js", "~/Scripts/jquery-migrate-{version}.js", "~/Scripts/jquery.validate.js", "~/Scripts/jquery.validate.messages_fr.js", "~/Scripts/moon.jquery.validation-{version}.js", "~/Scripts/jquery-ui-{version}.js" ).ForceOrdered());
更新了SoftLion提供的答案,以处理MVC 5(BundleFile vs FileInfo)中的更改。
internal class AsIsBundleOrderer : IBundleOrderer { public virtual IEnumerable<BundleFile> OrderFiles(BundleContext context, IEnumerable<BundleFile> files) { return files; } } internal static class BundleExtensions { public static Bundle ForceOrdered(this Bundle sb) { sb.Orderer = new AsIsBundleOrderer(); return sb; } }
用法:
bundles.Add(new ScriptBundle("~/content/js/site") .Include("~/content/scripts/jquery-{version}.js") .Include("~/content/scripts/bootstrap-{version}.js") .Include("~/content/scripts/jquery.validate-{version}") .ForceOrdered());
我喜欢使用stream利的语法,但它也适用于单个方法调用,并将所有脚本作为parameter passing。
您应该可以在BundleCollection.FileSetOrderList的帮助下设置顺序。 看看这个博客文章: http : //weblogs.asp.net/imranbaloch/archive/2012/09/30/hidden-options-of-asp-net-bundling-and-minification.aspx 。 你的例子中的代码将是这样的:
BundleFileSetOrdering bundleFileSetOrdering = new BundleFileSetOrdering("js"); bundleFileSetOrdering.Files.Add("~/Scripts/modernizr-*"); bundleFileSetOrdering.Files.Add("~/Scripts/json2.js"); bundleFileSetOrdering.Files.Add("~/Scripts/columnizer.js"); bundleFileSetOrdering.Files.Add("~/Scripts/jquery.ui.message.min.js"); bundleFileSetOrdering.Files.Add("~/Scripts/Shared/achievements.js"); bundleFileSetOrdering.Files.Add("~/Scripts/Shared/canvas.js"); bundles.FileSetOrderList.Add(bundleFileSetOrdering);
您应该考虑使用Cassette http://getcassette.net/它支持基于每个文件内的脚本引用自动检测脚本依赖关系。;
如果你喜欢坚持MS Web Optimization解决scheme,但喜欢根据脚本引用来安排脚本的想法,你应该阅读我的博客文章http://blogs.microsoft.co.il/oric/2013/12/27/building-single -page应用束-订货者/
@Darin Dimitrov的答案完全适合我,但我的项目是用VB编写的,所以这里是他的答案转换为VB
Public Class AsIsBundleOrderer Implements IBundleOrderer Public Function IBundleOrderer_OrderFiles(ByVal context As BundleContext, ByVal files As IEnumerable(Of FileInfo)) As IEnumerable(Of FileInfo) Implements IBundleOrderer.OrderFiles Return files End Function End Class
使用它:
Dim scriptBundleMain = New ScriptBundle("~/Scripts/myBundle") scriptBundleMain.Orderer = New AsIsBundleOrderer() scriptBundleMain.Include( "~/Scripts/file1.js", "~/Scripts/file2.js" ) bundles.Add(scriptBundleMain)