如何指定显式ScriptBundle包含订单?

jru*_*ell 91 asp.net-mvc bundle asp.net-mvc-4 asp.net-optimization

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

我有以下配置:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

以及以下观点:

<script type="text/javascript" src="@Scripts.Url(BundlePaths.CanvasScripts)"></script>
Run Code Online (Sandbox Code Playgroud)

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

<script type="text/javascript" src="/bundles/scripts/canvas?v=UTH3XqH0UXWjJzi-gtX03eU183BJNpFNg8anioG14_41"></script>
Run Code Online (Sandbox Code Playgroud)

到目前为止一切都很好,除了~/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足够聪明,可以找出依赖关系?

我还尝试了IBundleOrdererDarin Dimitrov在RTM中使用两种调试选项建议的实现,并且它的行为相同.

所以缩小版本不是我期望的顺序,但它的工作原理.

Dar*_*rov 114

您可以编写自定义捆绑包orderer(IBundleOrderer),以确保捆绑包含在您注册的顺序中:

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

然后:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在你看来:

@Scripts.Render("~/bundles/scripts/canvas")
Run Code Online (Sandbox Code Playgroud)

  • 这应该是有效的,但它也应该是不必要的,因为默认的orderer通常尊重包含的顺序(它只会将一些特殊文件提升到顶部,即jquery,reset.css/normalize.css等).它不应该是促进成就.js到顶部. (10认同)
  • 这适合我.根据http://stackoverflow.com/questions/17367736/jquery-ui-dialog-missing-close-icon我需要翻转它,它正在推广jqueryui而不是bootstrap. (2认同)

Sof*_*ion 52

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

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());
Run Code Online (Sandbox Code Playgroud)

  • 很漂亮!:D现在我必须在Interface方法签名中更改`BundleFile`的`FileInfo`.他们改变了它. (9认同)
  • @superjos我知道这已经很老了,但我会回答以防其他人有问题.它是System.Web.Optimization的一部分. (2认同)

Ger*_*vis 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

    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());
Run Code Online (Sandbox Code Playgroud)

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

  • 优秀.这应该包括在MS imho中 (4认同)
  • 适用于MVC 5.谢谢 (2认同)

Hao*_*ung 18

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

基于一个新的MVC4互联网应用程序网站,我对你的样本使用了类似的repro.

我添加到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); 
Run Code Online (Sandbox Code Playgroud)

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

<script src="@Scripts.Url("~/bundles/scripts/canvas")"></script>
Run Code Online (Sandbox Code Playgroud)

我验证了在捆绑的minified javascript中,achievement.js的内容是在modernizr之后......


Arn*_*ekk 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);
Run Code Online (Sandbox Code Playgroud)