Bundles do ASP.NET como desabilitar a minificação

185

Eu tenho debug="true"ambos os meus web.config (s) e simplesmente não quero meus pacotes compactados, mas nada que eu faça parece desativá-lo. Eu tentei enableoptimisations=false, aqui está o meu 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
fonte
2
@ RickAnd-MSFT A solicitação é como habilitar o pacote configurável enquanto a minificação está desativada. O uso do web.config debug = true / false ou EnableOptimizations somente ativa ou desativa. Resposta Martin Devillers' permite a agregação a ser ativado enquanto minification está desativado
guymid
2
também para mim .... para o arquivo 'x.js' no pacote configurável, verifique se NÃO existe um arquivo 'x.min.js' na pasta, caso contrário, embora você tenha removido a transformação de minificação .. o pacote configurável exibirá o 'pré' file minified por exemplo, se você tem 'angularjs' em seguida, exclua 'angular.min.js' ;-)
stooboo

Respostas:

137

Se você tem debug="true"em web.config e estão usando Scripts/Styles.Renderpara fazer referência os pacotes em suas páginas, que deve desligar ambos agregação e minification. BundleTable.EnableOptimizations = falsesempre desligará o agrupamento e a minificação (independentemente do sinalizador de depuração true / false).

Você talvez não esteja usando os Scripts/Styles.Renderajudantes? Se você estiver renderizando diretamente referências ao pacote, BundleTable.Bundles.ResolveBundleUrl()receberá sempre o conteúdo compactado / compactado.

Hao Kung
fonte
12
Com esta resposta, não sei como desativar a minificação e deixar o agrupamento no lugar - isso é possível?
Adam Tuliper - MSFT
33
Para fazer isso, o mais fácil seria alterar os Script / StyleBundles para os pacotes configuráveis ​​simples que não possuem transformação definida por padrão; isso desativaria a minificação, mas ainda o pacote configurável. Observe que você ainda precisa ter EnableOptimizations definido como true para que o pacote aconteça.
Hao Kung
2
também para mim .... para o arquivo 'x.js' no pacote configurável, verifique se NÃO existe um arquivo 'x.min.js' na pasta, caso contrário, embora você tenha removido a transformação de minificação .. o pacote configurável exibirá o 'pré' file minified por exemplo, se você tem 'angularjs' em seguida, exclua 'angular.min.js' ;-)
stooboo
1
@stooboo Isso foi o que o corrigiu para mim, mas você não precisa excluir nada. Basta incluir o arquivo não-min.
OneHoopyFrood
2
EnableOptimizations = false- onde esse código pertence?
23417 alex
158

As diretivas de compilação condicional são suas amigas:

#if DEBUG
            var jsBundle = new Bundle("~/Scripts/js");
#else
            var jsBundle = new ScriptBundle("~/Scripts/js");
#endif
Martin Devillers
fonte
16
Na verdade, acho que ele acertou em cheio - para desativar a minificação, use um Bundle conforme Hao, caso contrário, use ScriptBundle que empacota e minifica, não?
Adam Tuliper - MSFT
1
Essa é uma ótima solução quando você deseja fazer referência ao pacote configurável por seu URI de referência de pacote configurável para coisas como carregar via RequireJS sem usar o próprio sistema de pacote / minificação do RequireJS.
Norman H
1
Eu vejo coisas como Adam, eu entendo o ScriptBundle como um pacote aprimorado, portanto, como você deseja adicionar uma referência básica (sem pós-operações específicas), o Bundle me parece uma boa maneira de desativar a minificação em um pacote específico.
Charles HETIER 4/13/13
6
@ RickAnd-MSFT Acho que você está entendendo mal o objetivo deste código, que permite agrupar + sem minificação no modo de depuração e agrupar + minificação no modo de liberação. O uso do web.config debug = true / false ou EnableOptimizations somente ativa ou desativa. Eu li o seu comentário e rejeitou solução deste Martin, apenas para descobrir que ele é realmente uma maneira muito boa de ter agregação sem minification
guymid
-1 esta "solução" é uma lacuna na melhor das hipóteses. Na realidade, mesmo que funcione, leva a um código muito insustentável. Mas isso não é a pior coisa. O uso de "Bundle" leva os ativos a serem entregues pelo servidor com o tipo mime definido como "text / html" em vez de "text / javascript". Se você aplicar esta abordagem para agrupar arquivos css, você está brincando com o fire no modo de depuração. Não. Apenas não. Veja minha resposta para uma abordagem mais saudável, que funciona em compilações de produção.
XDS
89

Para desabilitar o agrupamento e a minificação, basta colocar este arquivo .aspx (isso desabilitará a otimização, mesmo debug=trueno web.config )

vb.net:

System.Web.Optimization.BundleTable.EnableOptimizations = false

c # .net

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

Se você colocar EnableOptimizations = trueisso, o pacote será compactado e minificado, mesmo que debug=trueem web.config

manuel
fonte
2
Essa é a única coisa que corrigiu o problema para mim. Eu tinha debug="true"o direito, Script.Rendermas ainda não estava funcionando. Observe também que isso não servirá nenhum arquivo .min.js., inclua cópias não minificadas do código de dependência.
OneHoopyFrood
2
@ TCC: estou errado em pensar que a sintaxe vb.net deve ter capital False?
jeremysawesome
@jeremysawesome oh sim, eu acho que é correto bom ponto, :-) Eu não sou um programador VB, muitas vezes, então eu nem percebeu ...
TCC
1
A primeira linha deve ser "... mesmo se debug = false" não?
UnionP
2
vb.Net não se importa sobre o caso, False = false, como .ToString () = .toString ()
manuel
68

Você pode desativar a minificação em seus pacotes configuráveis ​​simplesmente limpando suas transformações.

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

Pessoalmente, achei isso útil ao querer agrupar todos os meus scripts em um único arquivo, mas precisava de legibilidade durante as fases de depuração.

muglio
fonte
1
-1 Aqui estão os dragões: arrancar o JsMinifier / CssMinifier também arranca o mecanismo interno que define o tipo MIME para "text / css" ou "text / javascript". Isso não causa problemas no modo de depuração / liberação, mas causa estragos nos pacotes de css no contexto de compilações publicadas (também conhecidas como implantações ao vivo): o Chrome e o firefox se recusam a carregar os pacotes de css informando que seus tipos mime estão definidos como "text / html" em vez de "text / css". Com js-bundles, as coisas funcionam de alguma forma, mas é melhor ter um pacote js entregue como "text / html" (<- sério?). Veja minha resposta para a abordagem correta.
XDS 14/09
28

Tentei muitas dessas sugestões, mas a observação parecia funcionar. Eu perdi algumas horas apenas para descobrir que esse foi o meu erro:

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

Ele sempre possui javascript compactado e compactado, não importa o que eu tentei. Em vez disso, eu deveria ter usado isso:

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

O extra '~' fez isso. Até o removi novamente em apenas uma instância para ver se era realmente isso. Foi ... espero que eu possa salvar pelo menos uma pessoa as horas que perdi nisso.

usuario
fonte
Uau, eu estou ficando louco nas últimas 3 horas por causa disso ...
Bodokh 13/07
24

Combine várias respostas, isso funciona para mim no 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
fonte
21

Também existe uma maneira simples de controlar a minificação (e outros recursos) manualmente. É o novo transformador CssMinify () usando, assim:

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

Isso é conveniente quando você deseja ter alguns pacotes de peças especiais apenas para serem minificados. Digamos que você esteja usando alguns estilos padrão (jQuery), que estão ficando sob os seus pés (levando muitas solicitações excessivas de navegador para eles), mas você deseja manter a sua própria folha de estilo desminificada. (O mesmo - com javascript).

Agat
fonte
13

Combinei algumas respostas dadas por outras pessoas nesta pergunta para encontrar outra solução alternativa.

Objetivo: sempre agrupar os arquivos, desativar a minificação JS e CSS no caso em que <compilation debug="true" ... />e sempre aplicar uma transformação customizada ao pacote CSS.

Minha solução :

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

2) No 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
fonte
7

Se você definir a propriedade a seguir como false, ela desativará o pacote e a minificação.

No arquivo Global.asax.cs , adicione a linha conforme mencionado abaixo

protected void Application_Start()
{
    System.Web.Optimization.BundleTable.EnableOptimizations = false;
}
marvelTracker
fonte
Só não entendo por que meus menos arquivos são transformados em css quando tenho esse recurso desativado? Quando eu ativo a otimização, agrupar menos arquivos não funciona mais.
FrenkyB
5

Veja como desativar a minificação por pacote:

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

Nota: Os caminhos usados ​​para seus pacotes configuráveis ​​não devem coincidir com nenhum caminho real em suas compilações publicadas, caso contrário nada funcionará. Também evite usar .js, .css e / ou '.' e '_' em qualquer lugar no nome do pacote. Mantenha o nome o mais simples e direto possível, como no exemplo acima.

As classes auxiliares são mostradas abaixo. Observe que, para tornar essas classes à prova de futuro, removemos cirurgicamente as instâncias de minificação js / css em vez de usar .clear () e também inserimos uma transformação setter do tipo mime sem a qual as construções de produção provavelmente terão problemas, especialmente quando trata-se de entregar adequadamente pacotes de CSS (firefox e chrome rejeitam pacotes de CSS com o tipo mime definido como "text / html", que é o padrão):

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 fazer tudo isso funcionar, você precisa instalar (via nuget):

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

E seu web.config deve ser enriquecido da seguinte forma:

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

Note que você pode ter que tomar medidas extras para fazer seus pacotes de css funcionarem em termos de fontes etc. Mas isso é uma história diferente.

XDS
fonte
4

Apenas para complementar as respostas já fornecidas, se você também NÃO deseja reduzir / ofuscar / concatenar ALGUNS arquivos enquanto ainda permite agrupar e minificar completamente para outros arquivos, a melhor opção é usar um renderizador personalizado que lerá o conteúdo de um determinado pacote (s) e renderize os arquivos na página em vez de renderizar o caminho virtual do pacote. Eu pessoalmente exigi isso porque o IE 9 estava $ *% @ na cama quando meus arquivos CSS estavam sendo agrupados, mesmo com a minificação desativada .

Muito obrigado a este artigo , que me deu o ponto de partida para o código que eu usei para criar um renderizador CSS que renderizaria os arquivos para o CSS, mas ainda permitiria ao sistema renderizar meus arquivos javascript empacotados / minificados / ofuscados.

Criou a classe 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);
    }
  }

}

Em seguida, no arquivo de layout da navalha:

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

em vez do padrão:

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

Estou certo de que criar um renderizador opcional para arquivos javascript precisaria de pouco para atualizar também para esse auxiliar.

James Eby
fonte
1
Funciona bem. Se você deseja que os URLs mudem quando os arquivos são atualizados, você pode mudar CssTemplatepara algo como "<link href=\"{0}?f={1}\" rel=\"stylesheet\" type=\"text/css\" />"e mudar a sb.AppendFormatlinha para algo comosb.AppendFormat(CssTemplate + Environment.NewLine, urlHelper.Content(file.VirtualFile.VirtualPath), System.IO.File.GetLastWriteTimeUtc(HttpContext.Current.Server.MapPath(file.IncludedVirtualPath)).Ticks);
franzo
É verdade que fizemos algo muito parecido no trabalho. Tínhamos uma cadeia estática pública chamada JSVersion que colocamos na classe Global.asax, que extraiu o major / min / build / rev do assembly em execução. Em seguida, o referenciamos da seguinte maneira: <script type = "text / javascript" src = "Scripts / jsfile_name.js <% = Global.JSVersion%>"> </script>
James Eby
3

Pesquise por EnableOptimizationspalavras-chave em seu projeto

Então, se você encontrar

BundleTable.EnableOptimizations = true;

vire-o false.

BJ Patel
fonte
2
Isso desabilita a minificação, mas também desabilita completamente o agrupamento, o que eu acho que deveria ao menos ser observado.
John Pavek
1

Se você estiver usando a transformação CSS LESS / SASS, há uma opção useNativeMinificationque pode ser configurada como false para desativar a minificação (em web.config). Para meus propósitos, eu apenas a altero aqui quando preciso, mas você pode usar as transformações web.config para sempre habilitá-lo na compilação do release ou talvez encontrar uma maneira de modificá-lo no código.

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

Dica: O ponto principal disso é exibir o CSS, o que você pode fazer nas ferramentas de inspeção do navegador ou apenas abrindo o arquivo. Quando o pacote está ativado, o nome do arquivo é alterado em todas as compilações. Por isso, coloco o seguinte na parte superior da minha página para que eu possa visualizar meu CSS compilado com facilidade em uma nova janela do navegador toda vez que ele é alterado.

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

este será um URL dinâmico, algo como https://example.com/Content/css/bundlename?v=UGd0FjvFJz3ETxlNN9NVqNOeYMRrOkQAkYtB04KisCQ1


Atualização: criei uma transformação web.config para defini-la como verdadeira para mim durante a implantação da implantação / versão

  <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
fonte
1
O nome do arquivo NÃO muda em todas as compilações. Ele é baseado no conteúdo do arquivo e, portanto, muda sempre que o arquivo é alterado.
Jim Raden
1

Isto pode ser útil para alguém no futuro, como o novo quadro, quando a configuração através de VS, recebe um padrão web.config, web.Debug.confige web.Release.config. No web.release.configvocê encontrará esta linha:

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

isso parecia substituir as alterações em linha que eu fiz. Eu comentei esta linha e estávamos com molho (em termos de ver código não minificado em uma compilação "release")

Mutmatt
fonte