asp.net-mvc 如何指定显式的 ScriptBundle 包含顺序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11979718/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 02:10:16  来源:igfitidea点击:

How can I specify an explicit ScriptBundle include order?

asp.net-mvcasp.net-mvc-4bundleasp.net-optimization

提问by jrummell

I'm trying out the MVC4 System.Web.Optimization 1.0 ScriptBundle feature.

我正在尝试MVC4 System.Web.Optimization 1.0 ScriptBundle 功能

I have the following 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);
    }
}

and the following view:

以及以下观点:

<script type="text/javascript" src="@Scripts.Url(BundlePaths.CanvasScripts)"></script>

where BundlePaths.CanvasScriptsis "~/bundles/scripts/canvas". It renders this:

哪里BundlePaths.CanvasScripts"~/bundles/scripts/canvas"。它呈现这个:

<script type="text/javascript" src="/bundles/scripts/canvas?v=UTH3XqH0UXWjJzi-gtX03eU183BJNpFNg8anioG14_41"></script>

So far so good, except ~/Scripts/Shared/achievements.jsis the first script in the bundled source. It depends on every script included before it in the ScriptBundle. How can I ensure that it honors the order in which I add include statements to the bundle?

到目前为止一切顺利,除了~/Scripts/Shared/achievements.js捆绑源中的第一个脚本。这取决于ScriptBundle. 我如何确保它遵守我向包中添加包含语句的顺序?

Update

更新

This was a relatively new ASP.NET MVC 4 application, but it was referencing the optimization framework pre release package. I removed it and added the RTM package from http://nuget.org/packages/Microsoft.AspNet.Web.Optimization. With the RTM version with debug=true in web.config, @Scripts.Render("~/bundles/scripts/canvas")renders the individual script tags in the correct order.

这是一个相对较新的 ASP.NET MVC 4 应用程序,但它引用了优化框架预发布包。我删除了它并从http://nuget.org/packages/Microsoft.AspNet.Web.Optimization添加了 RTM 包。使用 web.config 中带有 debug=true 的 RTM 版本,@Scripts.Render("~/bundles/scripts/canvas")以正确的顺序呈现各个脚本标记。

With debug=false in web.config, the combined script has the achievements.js script first, but since its a function definition (object constructor) that's called later, it runs without error. Perhaps the minifier is smart enough to figure out dependencies?

使用 web.config 中的 debug=false 时,组合脚本首先具有 results.js 脚本,但由于它是稍后调用的函数定义(对象构造函数),因此它运行时不会出错。也许 minifier 足够聪明,可以找出依赖关系?

I also tried the IBundleOrdererimplementation that Darin Dimitrov suggested with RTM with both debug options and it behaved the same.

我还尝试了IBundleOrdererDarin Dimitrov 建议的带有两个调试选项的 RTM 实现,它的行为相同。

So the minified version is not in the order I expect, but it works.

所以缩小版本不是我期望的顺序,但它有效。

采纳答案by Hao Kung

I'm not seeing this behavior on the RTM bits, are you using the Microsoft ASP.NET Web Optimization Framework 1.0.0 bits: http://nuget.org/packages/Microsoft.AspNet.Web.Optimization?

我在 RTM 位上没有看到这种行为,您是否在使用 Microsoft ASP.NET Web Optimization Framework 1.0.0 位:http: //nuget.org/packages/Microsoft.AspNet.Web.Optimization

I used a similar repro to your sample, based off of a new MVC4 Internet application website.

我对您的示例使用了类似的复制品,基于一个新的 MVC4 Internet 应用程序网站。

I added to BundleConfig.RegisterBundles:

我添加到 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); 

And then in the default index page, I added:

然后在默认索引页面中,我添加了:

<script src="@Scripts.Url("~/bundles/scripts/canvas")"></script>

And I verified that in the minified javascript for the bundle, the contents of achievements.js was after modernizr...

我验证了在包的缩小的 javascript 中,performance.js 的内容是在 Modernizr 之后......

回答by Darin Dimitrov

You could write a custom bundle orderer (IBundleOrderer) that will ensure bundles are included in the order you register them:

你可以编写一个自定义的 bundle orderer ( IBundleOrderer) 来确保 bundle 包含在你注册它们的顺序中:

public class AsIsBundleOrderer : IBundleOrderer
{
    public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files)
    {
        return files;
    }
}

and then:

进而:

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);
    }
}

and in your view:

在您看来:

@Scripts.Render("~/bundles/scripts/canvas")

回答by Softlion

Thank you Darin. I've added an extension method.

谢谢达林。我添加了一个扩展方法。

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;
    }
}

Usage

用法

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());

回答by Gerald Davis

Updated the answer provided by SoftLion to handle changes in MVC 5 (BundleFile vs FileInfo).

更新了 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;
    }
}

Usage:

用法:

    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());

I like using fluent syntax but it also works with a single method call and all the scripts passed as parameters.

我喜欢使用流畅的语法,但它也适用于单个方法调用和作为参数传递的所有脚本。

回答by Arne H. Bitubekk

You should be able to set the order with help of the BundleCollection.FileSetOrderList. Have a look at this blog post: http://weblogs.asp.net/imranbaloch/archive/2012/09/30/hidden-options-of-asp-net-bundling-and-minification.aspx. The code in your instance would be something like:

您应该能够在 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);

回答by CBarr

@Darin Dimitrov's answer works perfectly for me, but my project is written in VB, so here's his answer converted to VB

@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

To Use it:

使用它:

Dim scriptBundleMain = New ScriptBundle("~/Scripts/myBundle")
scriptBundleMain.Orderer = New AsIsBundleOrderer()
scriptBundleMain.Include(
    "~/Scripts/file1.js",
    "~/Scripts/file2.js"
)
bundles.Add(scriptBundleMain)

回答by Ori Calvo

You should consider using Cassette http://getcassette.net/It supports auto detection of script dependencies based on script references found inside each file.

您应该考虑使用 Cassette http://getcassette.net/它支持根据在每个文件中找到的脚本引用自动检测脚本依赖项。

If you prefer sticking to MS Web Optimization solution but like the idea of arranging scripts based on script references you should read my blog post at http://blogs.microsoft.co.il/oric/2013/12/27/building-single-page-application-bundle-orderer/

如果您更喜欢坚持使用 MS Web 优化解决方案,但喜欢根据脚本引用安排脚本的想法,您应该阅读我的博客文章http://blogs.microsoft.co.il/oric/2013/12/27/building-single -page-application-bundle-orderer/