Paquetes de ASP.NET cómo deshabilitar la minificación

185

Tengo debug="true"en mi web.config (s) , y simplemente no quiero que mis paquetes se minimicen, pero nada de lo que hago parece deshabilitarlo. Lo intenté enableoptimisations=false, aquí está mi código:

//Javascript
bundles.Add(new ScriptBundle("~/bundles/MainJS")
            .Include("~/Scripts/regular/lib/mvc/jquery.validate.unobtrusive.js*")
            .Include("~/Scripts/regular/lib/mvc/jquery.validate*")
            .Include("~/Scripts/regular/lib/bootstrap.js")
            .IncludeDirectory("~/Scripts/regular/modules", "*.js", true)
            .IncludeDirectory("~/Scripts/regular/pages", "*.js", true)
            .IncludeDirectory("~/Scripts/regular/misc", "*.js", true));

//CSS
bundles.Add(new StyleBundle("~/bundles/MainCSS")
            .Include("~/Content/css/regular/lib/bootstrap.css*")
            .IncludeDirectory("~/Content/css/regular/modules", "*.css", true)
            .IncludeDirectory("~/Content/css/regular/pages", "*.css", true))
Baconbeastnz
fuente
2
@ RickAnd-MSFT La solicitud es cómo habilitar la agrupación mientras se deshabilita la minificación. El uso de web.config debug = true / false o EnableOptimizations solo activa o desactiva ambos. Martin respuesta Devillers' Permite la agrupación esté habilitado mientras minimización está desactivado
guymid
2
también para mí ... para el archivo 'x.js' en el paquete, asegúrese de que NO haya un archivo 'x.min.js' en la carpeta, de lo contrario, aunque haya eliminado la transformación de minificación ... la agrupación servirá archivo 'pre' minificado, por ejemplo, si tiene 'angular.js', entonces BORRAR 'angular.min.js' ;-)
stooboo

Respuestas:

137

Si tiene debug="true"en web.config y está utilizando Scripts/Styles.Renderpara hacer referencia a los paquetes en sus páginas, eso debería desactivar tanto la agrupación como la minificación. BundleTable.EnableOptimizations = falsesiempre desactivará tanto la agrupación como la minificación (independientemente del indicador de depuración verdadero / falso).

¿Quizás no estás usando los Scripts/Styles.Renderayudantes? Si representa directamente las referencias al paquete BundleTable.Bundles.ResolveBundleUrl(), siempre obtendrá el contenido minimizado / incluido.

Hao Kung
fuente
12
A partir de esta respuesta, no estoy seguro de cómo desactivar solo la minificación y dejar el paquete en su lugar: ¿es esto posible?
Adam Tuliper - MSFT
33
Para hacer esto, lo más fácil sería cambiar los Script / StyleBundles para Bundles simples que no tienen la Transformación establecida de forma predeterminada, esto desactivaría la minificación pero aún se agrupará. Tenga en cuenta que todavía tendría que tener EnableOptimizations establecido en true para que se realice la agrupación.
Hao Kung
2
también para mí ... para el archivo 'x.js' en el paquete, asegúrese de que NO haya un archivo 'x.min.js' en la carpeta, de lo contrario, aunque haya eliminado la transformación de minificación ... la agrupación servirá archivo 'pre' minimizado, por ejemplo, si tiene 'angular.js', entonces BORRAR 'angular.min.js' ;-)
stooboo
1
@stooboo Esto es lo que me solucionó, pero no necesita eliminar nada. Solo incluya el archivo no min.
OneHoopyFrood
2
EnableOptimizations = false- ¿A dónde pertenece este código?
alex
158

Las directivas de compilación condicional son tu amigo:

#if DEBUG
            var jsBundle = new Bundle("~/Scripts/js");
#else
            var jsBundle = new ScriptBundle("~/Scripts/js");
#endif
Martin Devillers
fuente
16
En realidad, creo que lo tiene clavado: para desactivar la minificación, use un paquete según Hao, de lo contrario use ScriptBundle que agrupa y minifica, ¿no?
Adam Tuliper - MSFT
1
Esta es una gran solución cuando desea hacer referencia al paquete por su URI de referencia de paquete para cosas como cargar a través de RequireJS sin usar el propio sistema de agrupación / minificación de RequireJS.
Norman H
1
Veo cosas como Adam, entiendo el ScriptBundle como un Bundle mejorado, por lo que dado que desea agregar una referencia básica (sin operaciones posteriores específicas), Bundle me parece una buena manera de desactivar la minificación en un paquete en particular.
Charles HETIER
66
@ RickAnd-MSFT Creo que está malinterpretando el propósito de este código que permite agrupar + no minificar en modo de depuración y agrupar + minificar en modo de liberación. El uso de web.config debug = true / false o EnableOptimizations solo activa o desactiva ambos. Leí tu comentario y descarté la solución de Martin, solo para descubrir que en realidad es una muy buena manera de tener paquetes sin
minificación
-1 esta "solución" es un stop-gap en el mejor de los casos. En realidad, aunque funciona, conduce a un código muy difícil de mantener. Pero eso no es lo peor de todo. El uso de "Bundle" lleva a que el servidor entregue los activos con el tipo mime configurado en "text / html" en lugar de "text / javascript". Si aplica este enfoque para agrupar archivos CSS, está jugando con fuego cuando está en modo de depuración. No lo hagas Solo no lo hagas. Vea mi respuesta para un enfoque más saludable que funciona en las compilaciones de producción.
XDS
89

Para deshabilitar la agrupación y la minificación, simplemente coloque este su archivo .aspx (esto deshabilitará la optimización incluso si está debug=trueen web.config )

vb.net:

System.Web.Optimization.BundleTable.EnableOptimizations = false

c # .net

System.Web.Optimization.BundleTable.EnableOptimizations = false;

Si coloca EnableOptimizations = trueesto, se agrupará y minimizará incluso si está debug=trueen web.config

manuel
fuente
2
Esto es lo único que solucionó el problema para mí. Tenía debug="true"y el derecho Script.Renderpero todavía no funcionaba. También tenga en cuenta que esto no servirá ningún archivo .min.js, así que asegúrese de incluir copias no minificadas del código de dependencia.
OneHoopyFrood
2
@TCC: ¿me equivoco al pensar que la sintaxis de vb.net debería tener mayúscula False?
jeremysawesome
@jeremysawesome oh sí, creo que es correcto, buen punto :-) No soy un programador de VB muy a menudo, así que ni siquiera me di cuenta ...
TCC
1
La primera línea debería ser "... incluso si debug = false" no?
UnionP
2
vb.Net no se preocupa por el caso, False = false, como .tostring () = .toString ()
manuel
68

Puede desactivar la minificación en sus paquetes simplemente borrando sus transformaciones.

var scriptBundle = new ScriptBundle("~/bundles/scriptBundle");
...
scriptBundle.Transforms.Clear();

Personalmente, esto me pareció útil cuando quería agrupar todos mis scripts en un solo archivo, pero necesitaba legibilidad durante las fases de depuración.

muglio
fuente
1
-1 Aquí hay dragones: arrancar el JsMinifier / CssMinifier también arranca el mecanismo interno que establece el tipo mime en "text / css" o "text / javascript". Esto no causa problemas en el modo de depuración / liberación, pero causa estragos en los paquetes css en el contexto de las compilaciones publicadas (también conocidas como implementaciones en vivo): Chrome y firefox se niegan a cargar dichos paquetes css indicando que sus tipos mime están configurados en "text / html" en lugar de "text / css". Con js-bundles, las cosas se ejercitan de alguna manera, pero en el mejor de los casos es sospechoso tener un js-bundle entregado como "text / html" (<- ¿en serio?). Vea mi respuesta para el enfoque correcto.
XDS
28

Intenté muchas de estas sugerencias, pero notar que parecía funcionar. He perdido bastantes horas solo para descubrir que este fue mi error:

@Scripts.Render("/bundles/foundation")

Siempre me ha minimizado y agrupado javascript, sin importar lo que haya intentado. En cambio, debería haber usado esto:

@Scripts.Render("~/bundles/foundation")

El '~' extra lo hizo. Incluso lo eliminé nuevamente en una sola instancia para ver si realmente era así. Fue ... espero poder salvar al menos a una persona las horas que desperdicié en esto.

Mella
fuente
Wow, me he vuelto loco durante las últimas 3 horas por esto ...
Bodokh
24

Combine varias respuestas, esto funciona para mí en ASP.NET MVC 4.

        bundles.Add(new ScriptBundle("~/Scripts/Common/js")
            .Include("~/Scripts/jquery-1.8.3.js")
            .Include("~/Scripts/zizhujy.com.js")
            .Include("~/Scripts/Globalize.js")
            .Include("~/Scripts/common.js")
            .Include("~/Scripts/requireLite/requireLite.js"));

        bundles.Add(new StyleBundle("~/Content/appLayoutStyles")
            .Include("~/Content/AppLayout.css"));

        bundles.Add(new StyleBundle("~/Content/css/App/FunGrapherStyles")
            .Include("~/Content/css/Apps/FunGrapher.css")
            .Include("~/Content/css/tables.css"));

#if DEBUG
        foreach (var bundle in BundleTable.Bundles)
        {
            bundle.Transforms.Clear();
        }
#endif
Jeff Tian
fuente
21

También hay una forma sencilla de controlar la minificación (y otras características) de forma manual. Es el nuevo transformador CssMinify () que usa, como este:

// this is in case when BundleTable.EnableOptimizations = false;
var myBundle = new StyleBundle("~/Content/themes/base/css")
    .Include("~/Content/themes/base/jquery.ui.core.css" /* , ... and so on */);
myBundle.Transforms.Add(new CssMinify());
bundles.Add(myBundle);

// or you can remove that transformer in opposite situation
myBundle.Transforms.Clear();

Eso es conveniente cuando quieres tener algunos paquetes de parte especial solo para ser minimizados. Digamos que está utilizando algunos estilos estándar (jQuery), que se están poniendo bajo sus pies (recibiendo muchas solicitudes excesivas del navegador), pero desea mantener sin minificar su propia hoja de estilos. (Lo mismo, con javascript).

Agat
fuente
13

Combiné algunas respuestas dadas por otros en esta pregunta para llegar a otra solución alternativa.

Objetivo: siempre agrupar los archivos, deshabilitar la minificación JS y CSS en caso de que <compilation debug="true" ... />y aplicar siempre una transformación personalizada al paquete CSS.

Mi solucion :

1) En web.config : <compilation debug="true" ... />

2) En el método Global.asax Application_Start () :

 protected void Application_Start() {
     ...
     BundleTable.EnableOptimizations = true; // Force bundling to occur

     // If the compilation node in web.config indicates debugging mode is enabled
     // then clear all transforms. I.e. disable Js and CSS minification.
     if (HttpContext.Current.IsDebuggingEnabled) {
         BundleTable.Bundles.ToList().ForEach(b => b.Transforms.Clear());
     }

      // Add a custom CSS bundle transformer. In my case the transformer replaces a
      // token in the CSS file with an AppConfig value representing the website URL
      // in the current environment. E.g. www.mydevwebsite in Dev and
      // www.myprodwebsite.com in Production.
      BundleTable.Bundles.ToList()
          .FindAll(x => x.GetType() == typeof(StyleBundle))
          .ForEach(b => b.Transforms.Add(new MyStyleBundleTransformer()));
     ...
}
Vince Horst
fuente
7

Si establece la siguiente propiedad en false, deshabilitará tanto la agrupación como la minificación.

En el archivo Global.asax.cs , agregue la línea como se menciona a continuación

protected void Application_Start()
{
    System.Web.Optimization.BundleTable.EnableOptimizations = false;
}
marvelTracker
fuente
Simplemente no entiendo por qué mis menos archivos se transforman en CSS cuando tengo esta función desactivada. Cuando habilito la optimización, agrupar menos archivos ya no funciona.
FrenkyB
5

Aquí se explica cómo deshabilitar la minificación por paquete:

bundles.Add(new StyleBundleRaw("~/Content/foobarcss").Include("/some/path/foobar.css"));
bundles.Add(new ScriptBundleRaw("~/Bundles/foobarjs").Include("/some/path/foobar.js"));

Nota al margen: las rutas utilizadas para sus paquetes no deben coincidir con ninguna ruta real en sus compilaciones publicadas, de lo contrario, nada funcionará. También asegúrese de evitar el uso de .js, .css y / o '.' y '_' en cualquier parte del nombre del paquete. Mantenga el nombre lo más simple y directo posible, como en el ejemplo anterior.

Las clases auxiliares se muestran a continuación. Tenga en cuenta que para hacer que estas clases estén preparadas para el futuro, eliminamos quirúrgicamente las instancias de minería js / css en lugar de usar .clear () y también insertamos una transformación mime-type-setter sin la cual las compilaciones de producción seguramente tendrán problemas, especialmente cuando se trata de entregar correctamente los paquetes css (firefox y chrome rechazan los paquetes css con el tipo mime establecido en "text / html", que es el valor predeterminado):

internal sealed class StyleBundleRaw : StyleBundle
{
        private static readonly BundleMimeType CssContentMimeType = new BundleMimeType("text/css");

        public StyleBundleRaw(string virtualPath) : this(virtualPath, cdnPath: null)
        {
        }

        public StyleBundleRaw(string virtualPath, string cdnPath) : base(virtualPath, cdnPath)
        {
                 Transforms.Add(CssContentMimeType); //0 vital
                 Transforms.Remove(Transforms.FirstOrDefault(x => x is CssMinify)); //0
        }
        //0 the guys at redmond in their infinite wisdom plugged the mimetype "text/css" right into cssminify    upon unwiring the minifier we
        //  need to somehow reenable the cssbundle to specify its mimetype otherwise it will advertise itself as html and wont load
}

internal sealed class ScriptBundleRaw : ScriptBundle
{
        private static readonly BundleMimeType JsContentMimeType = new BundleMimeType("text/javascript");

        public ScriptBundleRaw(string virtualPath) : this(virtualPath, cdnPath: null)
        {
        }

        public ScriptBundleRaw(string virtualPath, string cdnPath) : base(virtualPath, cdnPath)
        {
                 Transforms.Add(JsContentMimeType); //0 vital
                 Transforms.Remove(Transforms.FirstOrDefault(x => x is JsMinify)); //0
        }
        //0 the guys at redmond in their infinite wisdom plugged the mimetype "text/javascript" right into jsminify   upon unwiring the minifier we need
        //  to somehow reenable the jsbundle to specify its mimetype otherwise it will advertise itself as html causing it to be become unloadable by the browsers in published production builds
}

internal sealed class BundleMimeType : IBundleTransform
{
        private readonly string _mimeType;

        public BundleMimeType(string mimeType) { _mimeType = mimeType; }

        public void Process(BundleContext context, BundleResponse response)
        {
                 if (context == null)
                          throw new ArgumentNullException(nameof(context));
                 if (response == null)
                          throw new ArgumentNullException(nameof(response));

         response.ContentType = _mimeType;
        }
}

Para que todo funcione, debe instalar (a través de nuget):

WebGrease 1.6.0+ Microsoft.AspNet.Web.Optimization 1.1.3+

Y su web.config debería enriquecerse así:

<runtime>
       [...]
       <dependentAssembly>
        <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-x.y.z.t" newVersion="x.y.z.t" />
       </dependentAssembly>
       <dependentAssembly>
              <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-x.y.z.t" newVersion="x.y.z.t" />
       </dependentAssembly>
        [...]
</runtime>

<!-- setting mimetypes like we do right below is absolutely vital for published builds because for some reason the -->
<!-- iis servers in production environments somehow dont know how to handle otf eot and other font related files   -->
</system.webServer>
        [...]
        <staticContent>
      <!-- in case iis already has these mime types -->
      <remove fileExtension=".otf" />
      <remove fileExtension=".eot" />
      <remove fileExtension=".ttf" />
      <remove fileExtension=".woff" />
      <remove fileExtension=".woff2" />

      <mimeMap fileExtension=".otf" mimeType="font/otf" />
      <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
      <mimeMap fileExtension=".ttf" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
      <mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
      </staticContent>

      <!-- also vital otherwise published builds wont work  https://stackoverflow.com/a/13597128/863651  -->
      <modules runAllManagedModulesForAllRequests="true">
         <remove name="BundleModule" />
         <add name="BundleModule" type="System.Web.Optimization.BundleModule" />
      </modules>
      [...]
</system.webServer>

Tenga en cuenta que es posible que tenga que tomar medidas adicionales para que sus paquetes css funcionen en términos de fuentes, etc. Pero esa es una historia diferente.

XDS
fuente
4

Solo para complementar las respuestas ya dadas, si también NO desea minimizar / ofuscar / concatenar ALGUNOS archivos mientras aún permite la agrupación completa y la minificación para otros archivos, la mejor opción es ir con un renderizador personalizado que lea el contenido de un paquete en particular (s) y renderizar los archivos en la página en lugar de representar la ruta virtual del paquete. Personalmente, lo requería porque IE 9 costaba $ *% en la cama cuando mis archivos CSS se agrupaban incluso con la minificación desactivada .

Muchas gracias a este artículo , que me dio el punto de partida para el código que utilicé para crear un Renderizador CSS que representaría los archivos para el CSS pero aún permitiría que el sistema procese mis archivos javascript agrupados / minificados / ofuscados.

Creó la clase auxiliar estática:

using System;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;

namespace Helpers
{
  public static class OptionalCssBundler
  {
    const string CssTemplate = "<link href=\"{0}\" rel=\"stylesheet\" type=\"text/css\" />";

    public static MvcHtmlString ResolveBundleUrl(string bundleUrl, bool bundle)
    {
      return bundle ? BundledFiles(BundleTable.Bundles.ResolveBundleUrl(bundleUrl)) : UnbundledFiles(bundleUrl);
    }

    private static MvcHtmlString BundledFiles(string bundleVirtualPath)
    {
      return new MvcHtmlString(string.Format(CssTemplate, bundleVirtualPath));
    }

    private static MvcHtmlString UnbundledFiles(string bundleUrl)
    {
      var bundle = BundleTable.Bundles.GetBundleFor(bundleUrl);

      StringBuilder sb = new StringBuilder();
      var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);

      foreach (BundleFile file in bundle.EnumerateFiles(new BundleContext(new HttpContextWrapper(HttpContext.Current), BundleTable.Bundles, bundleUrl)))
      {
        sb.AppendFormat(CssTemplate + Environment.NewLine, urlHelper.Content(file.VirtualFile.VirtualPath));
      }

      return new MvcHtmlString(sb.ToString());
    }

    public static MvcHtmlString Render(string bundleUrl, bool bundle)
    {
      return ResolveBundleUrl(bundleUrl, bundle);
    }
  }

}

Luego, en el archivo de diseño de la maquinilla de afeitar:

@OptionalCssBundler.Render("~/Content/css", false)

en lugar del estándar:

@Styles.Render("~/Content/css")

Estoy seguro de que crear un renderizador opcional para archivos javascript también necesitaría poco para actualizar a este asistente.

James Eby
fuente
1
Funciona bien. Si desea que las URL cambien cuando se actualizan los archivos, puede cambiar CssTemplatea algo como "<link href=\"{0}?f={1}\" rel=\"stylesheet\" type=\"text/css\" />"y cambiar la sb.AppendFormatlínea a algo comosb.AppendFormat(CssTemplate + Environment.NewLine, urlHelper.Content(file.VirtualFile.VirtualPath), System.IO.File.GetLastWriteTimeUtc(HttpContext.Current.Server.MapPath(file.IncludedVirtualPath)).Ticks);
franzo
Es cierto que hicimos algo así en el trabajo. Teníamos una cadena estática pública llamada JSVersion que pusimos en la clase Global.asax que extrajo el maj / min / build / rev de la asamblea ejecutora. Luego lo referenciamos así: <script type = "text / javascript" src = "Scripts / jsfile_name.js <% = Global.JSVersion%>"> </script>
James Eby el
3

Busque la EnableOptimizationspalabra clave en su proyecto

Entonces si encuentras

BundleTable.EnableOptimizations = true;

dale la vuelta false.

BJ Patel
fuente
2
Esto deshabilita la minificación, pero también deshabilita la agrupación por completo, lo que creo que al menos debería tenerse en cuenta.
John Pavek
1

Si está utilizando la transformación CSS LESS / SASS, hay una opción useNativeMinificationque se puede establecer en falso para deshabilitar la minificación (en web.config). Para mis propósitos, solo lo cambio aquí cuando lo necesito, pero podría usar transformaciones web.config para habilitarlo siempre en la versión de lanzamiento o tal vez encontrar una forma de modificarlo en el código.

<less useNativeMinification="false" ieCompat="true" strictMath="false"
      strictUnits="false" dumpLineNumbers="None">

Consejo: El objetivo de esto es ver su CSS, lo que puede hacer en el navegador para inspeccionar las herramientas o simplemente abriendo el archivo. Cuando se habilita la agrupación, ese nombre de archivo cambia en cada compilación, por lo que pongo lo siguiente en la parte superior de mi página para que pueda ver fácilmente mi CSS compilado en una nueva ventana del navegador cada vez que cambia.

@if (Debugger.IsAttached) 
{
    <a href="@Styles.Url(ViewBag.CSS)" target="css">View CSS</a>
}

esta será una URL dinámica algo así como https://example.com/Content/css/bundlename?v=UGd0FjvFJz3ETxlNN9NVqNOeYMRrOkQAkYtB04KisCQ1


Actualización: creé una transformación web.config para configurarlo como verdadero durante la implementación / lanzamiento

  <bundleTransformer xmlns="http://tempuri.org/BundleTransformer.Configuration.xsd">
    <less xdt:Transform="Replace" useNativeMinification="true" ieCompat="true" strictMath="false" strictUnits="false" dumpLineNumbers="None">
      <jsEngine name="MsieJsEngine" />
    </less>
  </bundleTransformer>
Simon_Weaver
fuente
1
El nombre de archivo NO cambia en cada compilación. Se basa en el contenido del archivo, por lo que cambia cada vez que cambia el archivo.
Jim Raden
1

Esto puede llegar a ser útil a alguien en el futuro como el nuevo marco, cuando la configuración a través de VS, consigue un defecto web.config, web.Debug.configy web.Release.config. En el web.release.configencontrarás esta línea:

<compilation xdt:Transform="RemoveAttributes(debug)" />

Esto parecía anular cualquier cambio en línea que hice. Comenté esta línea y estábamos en salsa (en términos de ver código no minimizado en una compilación de "lanzamiento")

Mutmatt
fuente