asp.net-mvc - net - scripts render
¿Cómo puedo especificar un orden explícito de inclusión de ScriptBundle? (7)
Debería considerar el uso de Cassette http://getcassette.net/ Es compatible con la detección automática de dependencias de guiones basadas en referencias de guiones que se encuentran dentro de cada archivo.
Si prefiere seguir con la solución MS Web Optimization, pero al igual que la idea de organizar guiones basados en referencias de guiones, debe leer la publicación de mi blog en http://blogs.microsoft.co.il/oric/2013/12/27/building-single-page-application-bundle-orderer/
Estoy probando la característica ScriptBundle de MVC4 System.Web.Optimization 1.0 .
Tengo la siguiente configuración:
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);
}
}
y la siguiente vista:
<script type="text/javascript" src="@Scripts.Url(BundlePaths.CanvasScripts)"></script>
donde BundlePaths.CanvasScripts
es "~/bundles/scripts/canvas"
. Representa esto:
<script type="text/javascript" src="/bundles/scripts/canvas?v=UTH3XqH0UXWjJzi-gtX03eU183BJNpFNg8anioG14_41"></script>
Hasta ahora todo bien, excepto ~/Scripts/Shared/achievements.js
es el primer script en la fuente incluida. Depende de cada script incluido antes en ScriptBundle
. ¿Cómo puedo asegurarme de que respeta el orden en el que agrego las declaraciones de inclusión al paquete?
Actualizar
Esta era una aplicación ASP.NET MVC 4 relativamente nueva, pero hacía referencia al paquete de pre versión del marco de optimización. Lo eliminé y agregué el paquete RTM de http://nuget.org/packages/Microsoft.AspNet.Web.Optimization . Con la versión RTM con debug = true en web.config, @Scripts.Render("~/bundles/scripts/canvas")
representa las etiquetas de script individuales en el orden correcto.
Con debug = false en web.config, el script combinado tiene primero el script de achievements.js, pero dado que es una definición de función (constructor de objetos) que se llama más tarde, se ejecuta sin error. ¿Tal vez el minificador es lo suficientemente inteligente como para descubrir las dependencias?
También probé la implementación de IBundleOrderer
que Darin Dimitrov sugirió con RTM con ambas opciones de depuración y se comportó igual.
Entonces la versión minimizada no está en el orden que espero, pero funciona.
Debería poder establecer el orden con la ayuda de BundleCollection.FileSetOrderList. Eche un vistazo a esta publicación de blog: http://weblogs.asp.net/imranbaloch/archive/2012/09/30/hidden-options-of-asp-net-bundling-and-minification.aspx . El código en tu instancia sería algo así como:
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);
Gracias, Darin. He agregado un método de extensión.
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;
}
}
Uso
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());
La respuesta de @Darin Dimitrov funciona perfectamente para mí, pero mi proyecto está escrito en VB, así que aquí está su respuesta convertida a 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
Para usarlo:
Dim scriptBundleMain = New ScriptBundle("~/Scripts/myBundle")
scriptBundleMain.Orderer = New AsIsBundleOrderer()
scriptBundleMain.Include(
"~/Scripts/file1.js",
"~/Scripts/file2.js"
)
bundles.Add(scriptBundleMain)
No veo este comportamiento en los bits de RTM, ¿está utilizando Microsoft .NET Web Optimization Framework 1.0.0 bits: http://nuget.org/packages/Microsoft.AspNet.Web.Optimization ?
Utilicé una reproducción similar a su muestra, basada en un nuevo sitio web de la aplicación de Internet MVC4.
Añadí a 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);
Y luego en la página de índice predeterminada, agregué:
<script src="@Scripts.Url("~/bundles/scripts/canvas")"></script>
Y verifiqué que en el JavaScript miniaturizado para el paquete, el contenido de achievements.js estaba después de Modernizr ...
Puede escribir un IBundleOrderer
paquete personalizado ( IBundleOrderer
) que garantice que los paquetes estén incluidos en el orden en que los registra:
public class AsIsBundleOrderer : IBundleOrderer
{
public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files)
{
return files;
}
}
y entonces:
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);
}
}
y en su opinión:
@Scripts.Render("~/bundles/scripts/canvas")
Se actualizó la respuesta proporcionada por SoftLion para manejar los cambios en 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;
}
}
Uso:
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());
Me gusta usar sintaxis fluida, pero también funciona con una única llamada al método y todos los scripts pasaron como parámetros.