91 votes

Comment puis-je spécifier un ordre d'inclusion explicite de ScriptBundle ?

J'essaie le Fonctionnalité de ScriptBundle MVC4 System.Web.Optimization 1.0 .

J'ai la configuration suivante :

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

et la vue suivante :

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

BundlePaths.CanvasScripts es "~/bundles/scripts/canvas" . Il rend cela :

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

Jusqu'ici tout va bien, sauf que ~/Scripts/Shared/achievements.js est le premier script dans la source groupée. Il dépend de chaque script inclus avant lui dans le paquet de sources. ScriptBundle . Comment puis-je m'assurer qu'il respecte l'ordre dans lequel j'ajoute les déclarations d'inclusion au regroupement ?

Mise à jour

Il s'agissait d'une application ASP.NET MVC 4 relativement récente, mais elle faisait référence au package pre release du framework d'optimisation. Je l'ai supprimé et ajouté le package RTM de http://nuget.org/packages/Microsoft.AspNet.Web.Optimization . Avec la version RTM avec debug=true dans web.config, @Scripts.Render("~/bundles/scripts/canvas") rend les différentes balises script dans le bon ordre.

Avec debug=false dans web.config, le script combiné a les réalisations.js script en premier, mais comme il s'agit d'une définition de fonction (constructeur d'objet) qui est appelée plus tard, elle s'exécute sans erreur. Peut-être que le mineur est assez intelligent pour comprendre les dépendances ?

J'ai également essayé le IBundleOrderer que Darin Dimitrov a suggéré avec la RTM avec les deux options de débogage et le comportement est le même.

La version minifiée n'est donc pas dans l'ordre que j'attends, mais elle fonctionne.

114voto

Darin Dimitrov Points 528142

Vous pouvez écrire une commande de bundle personnalisée ( IBundleOrderer ) qui garantira que les paquets sont inclus dans l'ordre où vous les enregistrez :

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

et ensuite :

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

et dans votre vue :

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

52voto

Softlion Points 3410

Merci Darin. J'ai ajouté une méthode d'extension.

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

Utilisation

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

47voto

Gerald Davis Points 1120

Mise à jour de la réponse fournie par SoftLion pour utiliser la dernière version de MVC.

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

Utilisation :

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

J'aime l'enchaînement des .Include() au lieu d'une liste unique séparée par des virgules, mais les deux fonctionnent de la même manière.

18voto

Hao Kung Points 13035

Je ne vois pas ce comportement sur les bits RTM. Utilisez-vous les bits Microsoft ASP.NET Web Optimization Framework 1.0.0 ? http://nuget.org/packages/Microsoft.AspNet.Web.Optimization ?

J'ai utilisé un reproducteur similaire à votre exemple, basé sur un nouveau site d'application Internet MVC4.

J'ai ajouté à 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); 

Et puis dans la page d'index par défaut, j'ai ajouté :

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

Et j'ai vérifié que dans le javascript minifié pour le bundle, le contenu de achievements.js était après modernizr...

5voto

Arne HB Points 148

Vous devriez pouvoir définir l'ordre à l'aide de la fonction BundleCollection.FileSetOrderList. Jetez un coup d'œil à cet article de blog : http://weblogs.asp.net/imranbaloch/archive/2012/09/30/hidden-options-of-asp-net-bundling-and-minification.aspx . Le code dans votre instance serait quelque chose comme :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X