91

我正在尝试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);
    }
}

和以下观点:

<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. 如何确保它遵守我将包含语句添加到包的顺序?

更新

这是一个相对较新的 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 时,组合脚本首先具有成就.js 脚本,但由于它是稍后调用的函数定义(对象构造函数),因此它运行时不会出错。也许缩小器足够聪明,可以找出依赖关系?

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

所以缩小版本不是我期望的顺序,但它可以工作。

4

7 回答 7

116

您可以编写一个自定义捆绑订购程序 ( 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")
于 2012-08-16T05:40:57.497 回答
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;
    }
}

用法

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());
于 2013-05-08T09:44:50.383 回答
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());

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

于 2014-03-26T04:12:31.957 回答
18

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

我根据一个新的 MVC4 Internet 应用程序网站使用了与您的示例类似的复制品。

我添加到 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 中,results.js 的内容是在modernizr 之后......

于 2012-08-16T21:47:14.680 回答
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);
于 2013-06-17T10:16:48.380 回答
1

@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)
于 2013-06-18T21:15:06.337 回答
1

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

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

于 2014-01-02T13:11:41.340 回答