J'essaie la fonctionnalité MVC4 System.Web.Optimization 1.0 ScriptBundle .
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>
où BundlePaths.CanvasScripts
est "~/bundles/scripts/canvas"
. Cela rend ceci:
<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 de la source fournie. Cela dépend de chaque script inclus avant lui dans ScriptBundle
. Comment puis-je m'assurer qu'il respecte l'ordre dans lequel j'ajoute des instructions include au paquet?
Mettre à jour
Il s'agissait d'une application ASP.NET MVC 4 relativement nouvelle, mais elle faisait référence au package de version préliminaire de la structure d'optimisation. Je l'ai supprimé et ajouté le package RTM de http://nuget.org/packages/Microsoft.AspNet.Web.Optimization) . Avec le RTM version avec debug = true dans web.config, @Scripts.Render("~/bundles/scripts/canvas")
rend les balises de script individuelles dans le bon ordre.
Avec debug = false dans web.config, le script combiné a d'abord le script réalisations.js, mais puisqu'il s'agit d'une définition de fonction (constructeur d'objet) appelée ultérieurement, il s'exécute sans erreur. Peut-être que le minificateur est assez intelligent pour comprendre les dépendances?
J'ai aussi essayé l'implémentation de IBundleOrderer
que Darin Dimitrov a suggéré avec RTM) avec les deux options de débogage et le même comportement.
La version abrégée ne correspond donc pas à l'ordre que je prévois, mais cela fonctionne.
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é une reproduction similaire à votre exemple, basée sur un nouveau site Web 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é du bundle, le contenu de réalisations.js était postérieur à la modernisation ...
Vous pouvez écrire un bon de commande de bundles personnalisé ( IBundleOrderer
) pour vous assurer que les bundles sont inclus dans la commande que vous enregistrez:
public class AsIsBundleOrderer : IBundleOrderer
{
public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files)
{
return files;
}
}
et alors:
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 à votre avis:
@Scripts.Render("~/bundles/scripts/canvas")
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;
}
}
Usage
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());
Mise à jour de la réponse fournie par SoftLion pour gérer les modifications dans 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;
}
}
Usage:
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 utiliser une syntaxe fluide, mais cela fonctionne également avec un seul appel de méthode et tous les scripts passés en paramètres.
Vous devriez pouvoir définir la commande à l'aide de BundleCollection.FileSetOrderList. Jetez un coup d'œil à ce billet 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);
Vous devriez envisager d'utiliser Cassette http://getcassette.net/ Il prend en charge la détection automatique des dépendances de script en fonction des références de script trouvées dans chaque fichier.
Si vous préférez vous en tenir à la solution d'optimisation MS Web mais que vous aimez l'idée d'organiser des scripts basés sur des références de script, vous devriez lire mon billet de blog à l'adresse http://blogs.Microsoft.co.il/oric/2013/12/27)./building-single-page-application-bundle-orderer /
La réponse de @Darin Dimitrov fonctionne parfaitement pour moi, mais mon projet est écrit en VB, alors voici sa réponse convertie en 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
Pour l'utiliser:
Dim scriptBundleMain = New ScriptBundle("~/Scripts/myBundle")
scriptBundleMain.Orderer = New AsIsBundleOrderer()
scriptBundleMain.Include(
"~/Scripts/file1.js",
"~/Scripts/file2.js"
)
bundles.Add(scriptBundleMain)