Làm cách nào để chỉ định một thứ tự bao gồm ScriptBundle rõ ràng?


91

Tôi đang thử tính năng MVC4 System.Web.Optimization 1.0 ScriptBundle .

Tôi có cấu hình sau:

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

và chế độ xem sau:

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

nơi BundlePaths.CanvasScripts"~/bundles/scripts/canvas". Nó kết xuất điều này:

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

Cho đến nay rất tốt, ngoại trừ ~/Scripts/Shared/achievements.jstập lệnh đầu tiên trong nguồn được đóng gói. Nó phụ thuộc vào mọi tập lệnh được bao gồm trước nó trong ScriptBundle. Làm cách nào tôi có thể đảm bảo rằng nó tuân theo thứ tự mà tôi thêm các câu lệnh bao gồm vào gói?

Cập nhật

Đây là một ứng dụng ASP.NET MVC 4 tương đối mới, nhưng nó đang tham chiếu đến gói phát hành trước khung tối ưu hóa. Tôi đã xóa nó và thêm gói RTM từ http://nuget.org/packages/Microsoft.AspNet.Web.Optimization . Với phiên bản RTM có debug = true trong web.config, @Scripts.Render("~/bundles/scripts/canvas")hiển thị các thẻ script riêng lẻ theo đúng thứ tự.

Với debug = false trong web.config, trước tiên tập lệnh kết hợp có tập lệnh hits.js, nhưng vì định nghĩa hàm của nó (phương thức khởi tạo đối tượng) được gọi sau, nên nó chạy không có lỗi. Có lẽ trình thu nhỏ đủ thông minh để tìm ra sự phụ thuộc?

Tôi cũng đã thử IBundleOrderertriển khai mà Darin Dimitrov đề xuất với RTM với cả hai tùy chọn gỡ lỗi và nó hoạt động giống nhau.

Vì vậy, phiên bản thu nhỏ không theo thứ tự tôi mong đợi, nhưng nó hoạt động.

Câu trả lời:


18

Tôi không thấy hiện tượng này trên các bit RTM, bạn có đang sử dụng Microsoft ASP.NET Web Optimization Framework 1.0.0 bit: http://nuget.org/packages/Microsoft.AspNet.Web.Optimization không?

Tôi đã sử dụng một bản sao tương tự cho mẫu của bạn, dựa trên một trang web ứng dụng Internet MVC4 mới.

Tôi đã thêm vào 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); 

Và sau đó trong trang chỉ mục mặc định, tôi đã thêm:

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

Và tôi đã xác minh rằng trong javascript được rút gọn cho gói, nội dung của thành tích.js là sau hiện đại ...


Tôi đã nâng cấp lên phiên bản 1.0. Xem câu hỏi cập nhật của tôi. Nội dung của thành tích.js được đưa vào đầu tiên trong phiên bản thu nhỏ, nhưng nó hoạt động vì một hàm được gọi sau này.
jrummell

115

Bạn có thể viết một trình đặt hàng gói tùy chỉnh ( IBundleOrderer) sẽ đảm bảo các gói được bao gồm theo thứ tự bạn đăng ký:

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

và sau đó:

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

và theo quan điểm của bạn:

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

10
Điều này sẽ hoạt động, nhưng cũng không cần thiết, vì trình đặt hàng mặc định thường tôn trọng thứ tự của bao gồm (nó chỉ quảng bá một số tệp đặc biệt lên trên cùng, tức là jquery, reset.css / normalize.css, v.v.). Nó không nên quảng cáo thành tích.js lên đầu.
Hao Kung

1
@flipdoubt nộp một vấn đề ở đây với repro: aspnetoptimization.codeplex.com/workitem/list/advanced
Hảo Kung

1
Điều này hoạt động hoàn hảo, cảm ơn! Tôi đồng ý, mặc dù vậy, điều này không cần thiết.
CBarr

2
Điều này làm việc cho tôi. Nó đang quảng cáo jqueryui trên bootstrap khi theo stackoverflow.com/questions/17367736/… tôi cần nó lật.
Sethcran

1
@Hao Kung chúng ta có thể sắp xếp các tệp trong thư mục bao gồm không?
shaijut

52

Cảm ơn Darin. Tôi đã thêm một phương thức mở rộng.

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

Sử dụng

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

9
Khá bóng bẩy! : D Ngay bây giờ tôi đã phải thay đổi FileInfocho BundleFiletrong phương pháp chữ ký Interface. Họ đã thay đổi nó.
Leniel Maccaferri

vâng họ thay đổi nó trong phiên bản phát hành trước đó sử dụng khuôn khổ Owin
Softlion

chút Off-Topic: có ai có thêm thông tin về BundleFilelớp này không? Để đóng gói các tài nguyên nhúng, tôi đang cố gắng khởi tạo điều đó và nó yêu cầu một VirtualFiletham số (con cụ thể của) trong phương thức khởi tạo của nó.
superjos 13/09/13

Tôi có cùng một câu hỏi, tôi cần nhanh chóng BundleFile, nhưng không biết làm thế nào
Rui

2
@superjos Tôi biết điều này khá cũ nhưng tôi sẽ trả lời trong trường hợp có ai khác gặp vấn đề. Nó là một phần của System.Web.Optimization.
Talon

47

Đã cập nhật câu trả lời do SoftLion cung cấp để xử lý các thay đổi trong 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;
    }
}

Sử dụng:

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

Tôi thích sử dụng cú pháp thông thạo nhưng nó cũng hoạt động với một lệnh gọi phương thức duy nhất và tất cả các tập lệnh được truyền dưới dạng tham số.


2
Làm việc trong MVC 5. Cảm ơn
Pascal Carmoni

4
Thông minh. Điều này nên được bao gồm bởi MS IMHO
Angelo

hoạt động giống như một sự quyến rũ trong Biểu mẫu web ... về cơ bản nó sẽ hoạt động tốt cho tất cả các phiên bản mới nhất!
Sunny Sharma

Giải pháp rất sạch sẽ và đơn giản. Cảm ơn rất nhiều.
bunjeeb

5

Bạn sẽ có thể thiết lập thứ tự với sự trợ giúp của BundleCollection.FileSetOrderList. Hãy xem bài đăng trên blog này: http://weblogs.asp.net/imranbaloch/archive/2012/09/30/hiised-options-of-asp-net-bundling-and-minification.aspx . Mã trong trường hợp của bạn sẽ giống như sau:

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

1

Bạn nên xem xét sử dụng Cassette http://getcassette.net/ Nó hỗ trợ tự động phát hiện các phụ thuộc tập lệnh dựa trên các tham chiếu tập lệnh được tìm thấy bên trong mỗi tệp.

Nếu bạn thích gắn bó với giải pháp Tối ưu hóa web của MS nhưng thích ý tưởng sắp xếp tập lệnh dựa trên tham chiếu tập lệnh, bạn nên đọc bài đăng trên blog của tôi tại http://blogs.microsoft.co.il/oric/2013/12/27/building-single -trang-ứng dụng-gói-người đặt hàng /


1

Câu trả lời của @Darin Dimitrov hoàn toàn phù hợp với tôi, nhưng dự án của tôi được viết bằng VB, vì vậy đây là câu trả lời của anh ấy được chuyển đổi thành 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

Để dùng nó:

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

Tôi tiếp tục nhận được lỗi này: Class 'AsIsBundleOrderer' must implement 'Function OrderFiles(context as ....)' for interface 'System.Web.Optimization.IBundleOrderer'Bất kỳ ý tưởng?
Mark Pieszak - Trilon.io
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.