El paquete no incluye archivos .min

261

Tengo un problema extraño con el paquete mvc4 que no incluye archivos con extensión .min.js

En mi clase BundleConfig, declaro

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/Scripts/jquery")
        .Include("~/Scripts/jquery-1.8.0.js")
        .Include("~/Scripts/jquery.tmpl.min.js"));            
}

En mi opinión, declaro

<html>
    <head>
    @Scripts.Render("~/Scripts/jquery")
    </head><body>test</body>
</html>

Y cuando se procesa, solo se procesa

<html>
    <head>
         <script src="/Scripts/jquery-1.8.0.js"></script>
    </head>
    <body>test</body>
</html>

Si cambio el nombre de jquery.tmpl.min.js a jquery.tmpl.js (y actualizo la ruta en el paquete en consecuencia), ambos scripts se representan correctamente.

¿Hay alguna configuración que esté haciendo que ignore los archivos '.min.js'?

Fatal
fuente
Estoy usando el paquete MVC 4 e incluye archivos .min.js.
Eric J.
la versión RTM o el RC? para mí también funcionaba bien en el RC
Fatal
10
La idea es trabajar en modo de depuración, que se utilizará la versión "dev" sin minificación y, cuando esté en modo sin depuración, que se elija la versión minificada. Para verlo en acción, cambie su valor de depuración web.config de verdadero a falso.
Pieter Germishuys
28
sin embargo, en algunos casos no tiene la versión no minificada del script. Posiblemente podría entenderlo si ambos archivos existieran.
Fatal
1
Es una lástima que funcione así de forma predeterminada ... seguro, el archivo ya puede estar minimizado , pero creo que Microsoft no pudo ver el beneficio de agregar scripts preminificados a los paquetes con el fin de romper el caché (el pequeño vhash de parámetros agradable que se agrega a la URL y cambia cuando cambia el contenido del archivo)
necesario el

Respuestas:

257

La solución que publiqué originalmente es cuestionable (es un truco sucio). El comportamiento modificado ha cambiado en el paquete Microsoft.AspNet.Web.Optimization y el ajuste ya no funciona, como lo señalan muchos comentaristas. En este momento no puedo reproducir el problema en absoluto con la versión 1.1.3 del paquete.

Consulte las fuentes de System.Web.Optimization.BundleCollection (puede usar dotPeek, por ejemplo) para comprender mejor lo que está a punto de hacer. Lea también la respuesta de Max Shmelev .

Respuesta original :

Cambie el nombre de .min.js a .js o haga algo como

    public static void AddDefaultIgnorePatterns(IgnoreList ignoreList)
    {
        if (ignoreList == null)
            throw new ArgumentNullException("ignoreList");
        ignoreList.Ignore("*.intellisense.js");
        ignoreList.Ignore("*-vsdoc.js");
        ignoreList.Ignore("*.debug.js", OptimizationMode.WhenEnabled);
        //ignoreList.Ignore("*.min.js", OptimizationMode.WhenDisabled);
        ignoreList.Ignore("*.min.css", OptimizationMode.WhenDisabled);
    }

    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.IgnoreList.Clear();
        AddDefaultIgnorePatterns(bundles.IgnoreList);
        //NOTE: it's bundles.DirectoryFilter in Microsoft.AspNet.Web.Optimization.1.1.3 and not bundles.IgnoreList

        //...your code
     }
Pavel
fuente
44
Gracias de mí también, así que agregué esto a mi lista de objetos favoritos MVC4 :)
Dan B
27
este fue un momento largo, podrían haber estado agregando esos archivos min comentados con razón o algo por el resultado, ahora se perdió toda la hora preguntándose quién está robando mis archivos de script de la salida.
Giedrius
55
Según el comentario de Fatal en el OP, esta solución terminará redirigiendo referencias duplicadas para las versiones minimizadas y regulares si ambas existen (por ejemplo, jquery).
danmiser
11
M $, cuando somefile.min.js se especifica explícitamente, o cuando solo existe el archivo .min.js, ¡solo incluya el archivo .min.js! De lo contrario, solo aplica el comportamiento actual.
Adaptabi
3
Es increíble que la clase real se llame "IgnoreList", pero se deriva directamente de Object. Sin LINQ, sin iteración. - msdn.microsoft.com/en-us/library/…
JP ten Berge
176

Microsoft implica el siguiente comportamiento (y prefiero seguirlo en mis proyectos):

version corta

  1. Tiene versiones depuradas y minimizadas de un script en su proyecto en la misma carpeta:
    • script.js
    • script.min.js
  2. Solo agrega script.js a un paquete en su código.

Como resultado, tendrá automáticamente el script.js incluido en el modo DEBUG y script.min.js en el modo RELEASE .

Versión larga

También puede tener la versión .debug.js . En ese caso, el archivo se incluye en la siguiente prioridad en DEBUG:

  1. script.debug.js
  2. script.js

en LIBERACIÓN:

  1. script.min.js
  2. script.js

Nota

Y, por cierto, la única razón para tener un .min versiones de las secuencias de comandos en MVC4 es el caso cuando la versión minified no se puede procesar de forma automática. Por ejemplo, el siguiente código no se puede ofuscar automáticamente:

if (DEBUG) console.log("Debug message");

En todos los demás casos, puede utilizar solo una versión de depuración de su secuencia de comandos.

Max Shmelev
fuente
66
Sin embargo, una buena explicación, el problema del OP fue que algunos scripts ( jquery.tmpl) no tienen, no vienen con, no se descargaron la versión no mínima del archivo. El paquete ignora los archivos de script por completo si no tiene una versión no mínima en modo de depuración
Eonasdan
De acuerdo, buena explicación, pero no responde en absoluto a la pregunta de OP.
Diego
2
La versión corta no funcionó para mí. "script.js" se incluiría en estos dos tipos de versión. Cambié DEBUG / RELEASE y (cuando miré la fuente) 'script.js' fue el seleccionado / renderizado.
user981375
44
user981375, también debe configurar <compilation debug = "false" /> en el archivo web.config
Max Shmelev
55
Prefiero esta respuesta porque es un enfoque de "mejores prácticas" y explica cómo se pueden seguir las reglas predeterminadas del paquete para lograr el mismo objetivo.
James Reategui
5

Si todo lo que tiene es una versión minificada de un archivo, la solución más simple que he encontrado es copiar el archivo minificado, eliminar .min del nombre del archivo copiado, luego hacer referencia al nombre del archivo no minificado en su paquete.

Por ejemplo, supongamos que compró un componente js y le dieron un archivo llamado some-lib-3.2.1.min.js. Para usar este archivo en un paquete, haga lo siguiente:

  1. Copie some-lib-3.2.1.min.js y cambie el nombre del archivo copiado a some-lib-3.2.1.js. Incluya ambos archivos en su proyecto.

  2. Haga referencia al archivo no minificado en su paquete, así:

    bundles.Add(new ScriptBundle("~/bundles/libraries").Include(
        "~/Scripts/some-lib-{version}.js"
    ));
    

El hecho de que el archivo sin 'min' en el nombre esté realmente minimizado no debería causar ningún problema (aparte del hecho de que es esencialmente ilegible). Solo se usa en modo de depuración y se escribe como un script separado. Cuando no está en modo de depuración, el archivo min precompilado debe incluirse en su paquete.

joelfp
fuente
4

He encontrado una buena solución que funciona al menos en MVC5, solo puedes usarla en Bundlelugar de ScriptBundle. No tiene el comportamiento inteligente de lo ScriptBundleque no nos gusta (ignorando .min, etc.) en este caso. En mi solución, uso Bundlepara scripts de fiestas en 3D con archivos .min y .map y uso ScriptBundlepara nuestro código. No he notado ningún inconveniente de hacerlo. Para que funcione de esta manera, deberá agregar el archivo original, por ejemplo, angular.js, y cargará angular.js en depuración y agrupará angular.min.js en modo de liberación.

Ilya Chernomordik
fuente
Parece que no funciona cuando las optimizaciones están deshabilitadas ( ScriptTable.EnableOptimizations = false). Las rutas de guiones que contienen un patrón no se representan (p ~/Scripts/thirdpartylib/*.js. Ej .). Se hace el trabajo cuando EnableOptimizations = true, pero también lo hace ScriptBundle.
Steven Liekens el
También lo uso con falso (durante el desarrollo) y no tengo problemas que usted describa, por lo que podría ser algo más que lo esté afectando. También debe hacer IncludeDirectory en lugar de incluir para que el patrón funcione.
Ilya Chernomordik
¿Está seguro de que está representando la versión ".min.js" de su archivo? ¿Está utilizando paquetes del espacio de nombres System.Web.Optimizationso del paquete nuget Microsoft.Web.Optimizations?
Steven Liekens
Uso System.Web.Optimization y verifiqué que muestra la versión mínima, pero he descubierto que no utilizo IncludeDirectory, de hecho, pero sería extraño si eso no funcionara con la versión min ... Sin embargo, IncludeDirectory no es suficiente para mí, hago un escaneo personalizado y agrego todo el filtro usando Incluir, por lo que podría ser que el patrón e IncludeDirectory no funcionen correctamente allí, aunque es un poco extraño.
Ilya Chernomordik
1
No, el problema es doble: solo .min.jsexiste un archivo y el *.jspatrón no coincide con los archivos que terminan en .min.js.
Steven Liekens
3

Para renderizar *.min.jsarchivos, debe deshabilitar BundleTable.EnableOptimizations, que es una configuración global que se aplica a todos los paquetes.

Si desea habilitar optimizaciones solo para paquetes específicos, puede crear su propio ScriptBundletipo que habilite temporalmente las optimizaciones al enumerar archivos en el paquete.

public class OptimizedScriptBundle : ScriptBundle
{
    public OptimizedScriptBundle(string virtualPath)
        : base(virtualPath)
    {
    }

    public OptimizedScriptBundle(string virtualPath, string cdnPath)
        : base(virtualPath, cdnPath)
    {
    }

    public override IEnumerable<BundleFile> EnumerateFiles(BundleContext context)
    {
        if (context.EnableOptimizations)
            return base.EnumerateFiles(context);
        try
        {
            context.EnableOptimizations = true;
            return base.EnumerateFiles(context);
        }
        finally
        {
            context.EnableOptimizations = false;
        }
    }
}

Use en OptimizedScriptBundlelugar de ScriptBundlepara paquetes cuyo archivo minificado siempre debe usarse, independientemente de si existe un archivo no minificado.

Ejemplo de Kendo UI para ASP.NET MVC, que se distribuye como una colección de solo archivos minificados.

bundles.Add(new OptimizedScriptBundle("~/bundles/kendo")
        .Include(
            "~/Scripts/kendo/kendo.all.*",
            "~/Scripts/kendo/kendo.aspnetmvc.*",
            "~/Scripts/kendo/cultures/kendo.*",
            "~/Scripts/kendo/messages/kendo.*"));
Steven Liekens
fuente
Encontré algunos scripts que faltaban en una acción de publicación de producción, y pensando que era un problema de MVC, encontré esta respuesta ... he aquí, el kendo está involucrado. Después de haber trabajado durante demasiado tiempo, hago cualquier cosa para alejarme del kendo
Felipe
@Felipe Estaba en la misma situación, por eso escribí esta respuesta. Kendo es horrible. Espero que mi ejemplo sea útil.
Steven Liekens
2

Para mi caso, estaba usando la biblioteca (¡maravillosa!) Knockout.js que viene como versiones Debug / Non:

"~/Scripts/knockout-{Version}.js"
"~/Scripts/knockout-{Version}.Debug.js"

Para que esto funcione, incluí "Knockout- {Version} .js" (sin depuración) en mi Bundle y obtuve el .debug. archivo js en modo de depuración.

AcidPAT
fuente
1

Una manera fácil simplemente Cambie el nombre del archivo .min, por ejemplo, tiene abc.min.css que simplemente cambie el nombre de este archivo a abc_min.css y agréguelo a su paquete. Sé que no es la forma correcta de hacerlo, sino solo una solución temporal. Gracias y feliz codificación.

RK Sharma
fuente
1
Cada vez que Nuget descargue el archivo, debe cambiarle el nombre.
Anirudha Gupta
Sé que no es la forma correcta de hacerlo, sino solo una solución temporal
RK Sharma
1
poner esta línea me funciona // BundleTable.EnableOptimizations = true;
Anirudha Gupta
0

Bundler tiene muchos beneficios, consulte esta página PERO :

La plataforma MVC4 de Microsoft considera que tiene al menos una versión minimizada y una versión no minificada para cada Script o Style Bundle (también están disponibles otros archivos como Debug y vsdoc). Por lo tanto, tenemos problemas en situaciones en las que solo hay uno de estos archivos.

Puede cambiar el estado de depuración en el archivo web.config de forma permanente para manejar la salida:

<compilation debug="false" targetFramework="4.0" />

Ver los cambios de salida! Se modificó el filtrado de archivos. Para cumplir con el propósito, debemos cambiar ignorar la filtración de casos que cambiará la lógica de la aplicación.

Amirhossein Mehrvarzi
fuente
1
Agregar debug = "false" todavía no funciona para mí. Los archivos min.js todavía no están incluidos, aunque borro la IgnoreList también ...
MoSs
-21

Amigos, simplemente lo mantendría simplemente hasta que Microsoft lo haga actuar juntos

Prueba esto

En RegisterBundles, cree este paquete para Kendo

bundles.Add(new StyleBundle("~/Content/kendo/css").Include(
                    "~/Content/kendo/2012.3.1121/kendo.common.min.css",
                     "~/Content/kendo/2012.3.1121/kendo.dataviz.min.css",
                      "~/Content/kendo/2012.3.1121/kendo.blueopal.min.css"
 ));

En _Layout.cshtml pon esto:

@if (HttpContext.Current.IsDebuggingEnabled)
 { 
<link href="@Url.Content("~/Content/kendo/2012.3.1121/kendo.common.min.css")"      
rel="stylesheet"  type="text/css" />
<link href="@Url.Content("~/Content/kendo/2012.3.1121/kendo.dataviz.min.css")" 
rel="stylesheet" type="text/css" />   
<link href="@Url.Content("~/Content/kendo/2012.3.1121/kendo.blueopal.min.css")"    
rel="stylesheet" type="text/css" />
 }
 else
 {
     @Styles.Render("~/Content/kendo/css")   
 }

De esta forma, obtenemos los mejores paquetes en producción y una referencia en depuración

Arreglalo cuando Microsoft arregle su código MVC 4

usuario1819794
fuente
3
No soy fanático de esta solución propuesta en absoluto. Ahora tiene que mantener el conjunto de scripts en (al menos) dos lugares
Fatal
Esto prácticamente anula el propósito de la agrupación, ¿no crees?
Oliver
44
La agrupación ya funciona de esta manera. Si ejecuta el proyecto en modo de depuración, cada archivo CSS se carga individualmente, sin embargo, cuando se ejecuta en versión, se combinan y se minimizan en uno. El código dentro del bloque if es idéntico al que se muestra en la página automáticamente en modo de depuración.
Chad Levy