我正在尝试MVC4 System.Web.Optimization 1.0 ScriptBundle feature。
我有以下配置:
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,组合脚本首先使用achievement.js脚本,但由于它是稍后调用的函数定义(对象构造函数),因此它运行时没有错误。也许minifier足够聪明,可以找出依赖关系?
我还尝试了Darin Dimitrov在RTM中使用两种调试选项建议的IBundleOrderer
实现,并且它的行为相同。
所以缩小的版本不是我期望的顺序,但是它有效。
答案 0 :(得分:112)
您可以编写自定义捆绑订单(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")
答案 1 :(得分:51)
谢谢Darin。我添加了一个扩展方法。
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());
答案 2 :(得分:47)
更新了SoftLion提供的答案,以处理MVC 5中的更改(BundleFile与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());
我喜欢使用流利的语法,但它也适用于单个方法调用和所有脚本作为参数传递。
答案 3 :(得分:17)
我没有在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的内容是在modernizr之后......
答案 4 :(得分:5)
您应该可以在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);
答案 5 :(得分:1)
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)
答案 6 :(得分:1)
您应该考虑使用Cassette http://getcassette.net/它支持基于每个文件中的脚本引用自动检测脚本依赖项。
如果您更喜欢坚持使用MS Web优化解决方案,但想要根据脚本引用安排脚本,那么您应该在http://blogs.microsoft.co.il/oric/2013/12/27/building-single-page-application-bundle-orderer/
阅读我的博客文章