Açık bir ScriptBundle dahil etme sırasını nasıl belirtebilirim?


91

Ben dışarı çalışıyorum MVC4 System.Web.Optimization 1.0 ScriptBundle özelliğini .

Aşağıdaki yapılandırmaya sahibim:

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

ve aşağıdaki görünüm:

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

nerede BundlePaths.CanvasScriptsolduğunu "~/bundles/scripts/canvas". Bunu yapar:

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

Şimdiye kadar çok iyi, ancak ~/Scripts/Shared/achievements.jspaketlenmiş kaynaktaki ilk komut dosyası. Önünde bulunan her betiğe bağlıdır ScriptBundle. Pakete dahil etme ifadelerini eklediğim sırayı karşıladığından nasıl emin olabilirim?

Güncelleme

Bu nispeten yeni bir ASP.NET MVC 4 uygulamasıydı, ancak optimizasyon çerçevesi ön yayın paketine başvuruyordu. Onu kaldırdım ve http://nuget.org/packages/Microsoft.AspNet.Web.Optimization'dan RTM paketini ekledim . Web.config dosyasında debug = true olan RTM sürümü ile @Scripts.Render("~/bundles/scripts/canvas")ayrı komut dosyası etiketlerini doğru sırada işler.

Web.config dosyasında debug = false ile, birleşik komut dosyası önce achievements.js komut dosyasını içerir, ancak daha sonra çağrılan bir işlev tanımı (nesne yapıcısı) olduğu için hatasız çalışır. Minifier, bağımlılıkları çözecek kadar akıllı olabilir mi?

IBundleOrdererDarin Dimitrov'un RTM ile önerdiği uygulamayı her iki hata ayıklama seçeneğiyle de denedim ve aynı şekilde davrandı.

Yani küçültülmüş versiyon beklediğim sırada değil ama çalışıyor.

Yanıtlar:


18

Bu davranışı RTM bitlerinde görmüyorum, Microsoft ASP.NET Web Optimization Framework 1.0.0 bitlerini kullanıyor musunuz : http://nuget.org/packages/Microsoft.AspNet.Web.Optimization ?

Yeni bir MVC4 İnternet uygulaması web sitesine dayalı olarak örneğiniz için benzer bir repro kullandım.

BundleConfig.RegisterBundles'a ekledim:

        Bundle canvasScripts =
            new ScriptBundle("~/bundles/scripts/canvas")
                .Include("~/Scripts/modernizr-*")
                .Include("~/Scripts/Shared/achievements.js")
                .Include("~/Scripts/Shared/canvas.js");
        bundles.Add(canvasScripts); 

Ve sonra varsayılan dizin sayfasına şunu ekledim:

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

Ve paket için küçültülmüş javascript'te, achievements.js'nin içeriğinin modernizr'den sonra olduğunu doğruladım ...


1.0 sürümüne yükselttim. Güncellenen soruma bakın. Achievements.js'nin içeriği ilk olarak küçültülmüş sürüme dahil edilir, ancak daha sonra çağrılan bir işlev olduğundan çalışır.
jrummell

115

IBundleOrdererPaketlerin kaydettiğiniz sıraya dahil edilmesini sağlayacak özel bir paket sıralayıcısı ( ) yazabilirsiniz :

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

ve sonra:

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

ve size göre:

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

10
Bu işe yaramalı, ancak aynı zamanda gereksiz de olmalıdır, çünkü varsayılan düzenleyici genellikle içerme sırasına saygı duyar (yalnızca birkaç özel dosyayı en üste taşır, yani jquery, reset.css / normalize.css, vb.). Achievements.js'yi en üste yükseltmemelidir.
Hao Kung

1
@flipdoubt repro ile buraya bir sorun kaydedin
Hao Kung

1
Bu harika çalışıyor, teşekkürler! Yine de buna katılıyorum, bu gerekli olmamalı.
CBarr

2
Bu benim için çalışıyor. Stackoverflow.com/questions/17367736/… 'a göre jqueryui'yi bootstrap üzerinden destekliyordu .
Sethcran

1
@Hao Kung include dizinindeki dosyaları sipariş edebilir miyiz ?
Shaiju T

52

Teşekkürler Darin. Bir uzatma yöntemi ekledim.

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

Kullanım

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
Oldukça şık! : D Şu an değişim gerekiyordu FileInfoiçin BundleFilearabirim yöntemi imzası. Değiştirdiler.
Leniel Maccaferri

evet, bunu Owin çerçevesini kullanan yayın öncesi sürümde değiştirdiler
Softlion

Küçük Konu Dışı: Bu BundleFilesınıfla ilgili daha fazla bilgisi olan var mı? Gömülü kaynakları bir araya getirmek için, bunu başlatmaya çalışıyorum VirtualFileve yapıcısında bir (somut çocuk) parametresi gerektiriyor .
superjos

Aynı sorum var, BundleFile örneğini oluşturmam gerekiyor, ancak nasıl yapılacağını bilmiyorum
Rui

2
@superjos Bunun oldukça eski olduğunu biliyorum ama başka birinin sorunu olması durumunda cevap vereceğim. System.Web.Optimization'ın bir parçasıdır.
Talon

47

MVC 5'teki (BundleFile vs FileInfo) değişiklikleri işlemek için SoftLion tarafından sağlanan yanıt güncellendi.

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

Kullanım:

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

Akıcı sözdizimi kullanmayı severim ama aynı zamanda tek bir yöntem çağrısı ve parametreler olarak aktarılan tüm komut dosyaları ile çalışır.


2
MVC 5'te çalışıyor. Teşekkürler
Pascal Carmoni

4
Mükemmel. Bu MS imho tarafından eklenmelidir
Angelo

Web Formlarında da bir cazibe gibi çalışır ... temelde tüm son sürümler için iyi çalışmalıdır!
Sunny Sharma

Çok temiz ve basit bir çözüm. Çok teşekkürler.
bunjeeb

5

BundleCollection.FileSetOrderList yardımıyla siparişi ayarlayabilmelisiniz. Bu blog gönderisine bir göz atın: http://weblogs.asp.net/imranbaloch/archive/2012/09/30/hidden-options-of-asp-net-bundling-and-minification.aspx . Örneğinizdeki kod şu şekilde olacaktır:

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

Kaset http://getcassette.net/ kullanmayı düşünmelisiniz . Her dosyanın içinde bulunan komut dosyası referanslarına göre komut dosyası bağımlılıklarının otomatik olarak algılanmasını destekler.

MS Web Optimizasyonu çözümüne bağlı kalmayı tercih ediyor, ancak komut dosyalarını komut dosyası referanslarına göre düzenleme fikrini seviyorsanız, http://blogs.microsoft.co.il/oric/2013/12/27/building-single adresindeki blog yazımı okumalısınız. -page-application-bundle-orderer /


1

@Darin Dimitrov'un cevabı benim için mükemmel çalışıyor, ancak projem VB'de yazılmış, bu yüzden cevabı VB'ye dönüştürüldü

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

Kullanmak için:

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

Şu hatayı alıyorum: Class 'AsIsBundleOrderer' must implement 'Function OrderFiles(context as ....)' for interface 'System.Web.Optimization.IBundleOrderer'Herhangi bir fikrin var mı?
Mark Pieszak - Trilon.io
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.