11

sto usando la nuova System.Web.Optimization e ho creato un fascio come questo:GZip fasci system.web.optimization

bundles.Add(New ScriptBundle("~/bundles/BaseJS").Include(
       "~/Resources/Core/Javascripts/jquery-1.7.1.js", 
       "~/Resources/Core/Javascripts/jquery-ui-1.8.16.js", 
       "~/Resources/Core/Javascripts/jquery.validate.js", 
       "~/Resources/Core/Javascripts/jquery.validate.unobtrusive.js", 
       "~/Resources/Core/Javascripts/jquery.unobtrusive-ajax.js")) 

e, a mio avviso ho aggiunto questo

@System.Web.Optimization.Scripts.Render("~/bundles/BaseJS") 

Nel violinista l'URL ha un header di scadenza di 1 anno in futuro e un tipo di contenuto di testo/javascript

Nel web.config ho del codice per gzip che sta lavorando su file JS statici ma non lo fa t sembra sui pacchetti miniati.

<staticContent> 
    <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00"/> 
    <remove fileExtension=".js"/> 
    <mimeMap fileExtension=".js" mimeType="text/javascript"/> 
</staticContent> 
<urlCompression doDynamicCompression="true" doStaticCompression="true" dynamicCompressionBeforeCache="true"/> 
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files"> 
    <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/> 
    <dynamicTypes> 
    <add mimeType="text/*" enabled="true"/> 
    <add mimeType="text/javascript" enabled="true"/> 
    </dynamicTypes> 
    <staticTypes> 
    <add mimeType="text/*" enabled="true"/> 
    <add mimeType="text/javascript" enabled="true"/> 
    </staticTypes> 
</httpCompression> 

C'è un modo per rendere il pacchetto di rendering gzip del contenuto?

+0

Penso che questo possa essere possibile con un iBundleTransform, ma io non sono sicuro di come. https://twitter.com/ericdc1/status/219850852364599298 – ericdc

risposta

12

come avrete notato, la creazione di un fascio trasformazione personalizzata con la creazione di una classe che implementa IBundleTransform è la strada giusta da percorrere. Ad esempio, il seguente è un esempio fascio di trasformare che utilizza lo SharpZipLib (via NuGet) per fare la compressione gzip:

public class GZipTransform : IBundleTransform 
{ 
    string _contentType; 

    public GZipTransform(string contentType) 
    { 
     _contentType = contentType; 
    } 

    public void Process(BundleContext context, BundleResponse response) 
    { 
     var contentBytes = new UTF8Encoding().GetBytes(response.Content); 

     var outputStream = new MemoryStream(); 
     var gzipOutputStream = new GZipOutputStream(outputStream); 
     gzipOutputStream.Write(contentBytes, 0, contentBytes.Length); 

     var outputBytes = outputStream.GetBuffer(); 
     response.Content = Convert.ToBase64String(outputBytes); 


     // NOTE: this part is broken 
     context.HttpContext.Response.Headers["Content-Encoding"] = "gzip"; 
     response.ContentType = _contentType ; 
    } 
} 

Ora, ecco la parte sfortunata - nel testare questo esempio, ho scoperto un bug che non mancherà di tenere da lavoro. Il progetto originale prevede che la gente farebbe cose piuttosto semplici - e come tale, BundleResponse espone proprietà che consentono di impostare i contenuti (più specificatamente, il contenuto stringa) e il tipo di contenuto. Il BundleContext espone una proprietà di HttpContext, che porterebbe una persona ragionevole ritenere che proprietà aggiuntive di risposta potrebbero essere fissati lì (come indicato sopra). Tuttavia, questo è fuorviante per 2 motivi:

  1. trasformate bundle vengono eseguiti come parte della creazione del fascio - e creando il fascio accade la prima volta che viene fatto riferimento (non dereferenziata, come in, il browser segue il attributo src in un tag script - ma con riferimento, come in, la vista chiama il metodo helper Scripts.Render). Nel mio esempio di cui sopra, questo significa che un'intestazione Content-Encoding con un valore di gzip sarà impostato sulla prima pagina con una vista che utilizza metodi di supporto di bundling per generare un link - e se il contenuto HTTP reale non è compresso con gzip, è' Riceverò un errore poiché il browser non può decodificare il contenuto HTTP.

  2. Anche se il numero 1 non è stato un problema, il pacchetto viene messo immediatamente nella cache di ASP.NET dopo la sua creazione, quindi questo percorso di codice verrà eseguito solo una volta.

Stiamo prendendo uno sguardo duro al disegno nella prossima versione del framework per consentire di specificare tutti (idealmente) gli aspetti del messaggio di risposta HTTP che è libero del contesto HTTP (che significa che è facilmente cachable).

Una nota aggiuntiva. Per alimentare trasforma fascio personalizzato, sarà necessario ripiegare a creare un'istanza di bundle piuttosto che ScriptBundle/StyleBundle. Queste classi sono in realtà solo tipi abbreviati per bundle con trasformazioni di bundle preconfigurate.Per creare un pacchetto in base a Bundle, si dovrebbe fare qualcosa di simile alla seguente:

var jqueryBundle = new Bundle("~/bundles/jqueryall", new GZipTransform("text/javascript")); 
jqueryBundle.Include("~/Scripts/jquery-1.*", 
    "~/Scripts/jquery-ui*", 
    "~/Scripts/jquery.unobtrusive*", 
    "~/Scripts/jquery.validate*"); 
bundles.Add(jqueryBundle); 
+4

Si scopre che IIS Dynamic Content Compression fa tutto questo senza alcuna cerimonia. Nel mio caso ho dovuto IISReset dopo aver installato DCC per farlo funzionare, quindi sono stato indotto a pensare che system.web.optimization necessitava di un intervento su gzip ma non è così. – ericdc

+0

Scrivi "Diamo un'occhiata al design nella prossima versione del framework ...", quindi suppongo che tu sia un membro del team di ASP.NET. Stai pensando di consentire il contenuto di byte nella prossima versione? Ciò sarebbe estremamente utile per il raggruppamento di immagini (sprite). – JohannesH

+2

Questo problema è stato risolto in System.Web.Optimizations? Sono in un ambiente in cui non riesco a utilizzare IIS Compression, quindi questo sembra l'unico modo percorribile diverso dall'utilizzo di un HttpModule. – kkara

5

Può essere raggiunto utilizzando HttpModule

public class GzipModule : IHttpModule 
{ 
    #region IHttpModule Members 

    public void Init(HttpApplication application) 
    { 
     application.BeginRequest += Application_BeginRequest; 
    } 

    public void Dispose() 
    { 
    } 

    #endregion 

    private void Application_BeginRequest(Object source, EventArgs e) 
    { 
     HttpContext context = HttpContext.Current; 
     HttpRequest request = context.Request; 
     HttpResponse response = context.Response; 
     string acceptEncoding = request.Headers["Accept-Encoding"]; 

     if (String.IsNullOrEmpty(acceptEncoding)) 
      return; 

     acceptEncoding = acceptEncoding.ToUpperInvariant(); 

     if (acceptEncoding.Contains("GZIP")) 
     { 
      response.AppendHeader("Content-Encoding", "gzip"); 
      response.Filter = new GZipStream(response.Filter, CompressionMode.Compress); 
     } 
     else if (acceptEncoding.Contains("DEFLATE")) 
     { 
      response.AppendHeader("Content-Encoding", "deflate"); 
      response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress); 
     } 
    } 
} 

con registrazione nel config

<system.webServer> 
    <modules> 
     <add name="Gzip" type="Gecko.Web.GzipModule" /> 
    </modules> 
+2

Vero, ma ora verrà eseguito per TUTTE le richieste, non semplicemente per i pacchetti. –

11

Con il ultima ASP.NET Optimization (v1.1.2), la classe GZipTransform non funziona bene.

ho trovato un nuovo modo con un costume Bundle classe che sarà sempre comprimere il contenuto fascio (che è stata trasformata e cache) prima della risposta:

public class GZipBundle : Bundle 
{ 
    public GZipBundle(string virtualPath, params IBundleTransform[] transforms) 
     : base(virtualPath, null, transforms) { } 

    public override BundleResponse CacheLookup(BundleContext context) 
    { 
     if (null != context) GZipEncodePage(context.HttpContext); 
     return base.CacheLookup(context); 
    } 

    // Sets up the current page or handler to use GZip through a Response.Filter. 
    public static void GZipEncodePage(HttpContextBase httpContext) 
    { 
     if (null != httpContext && null != httpContext.Request && null != httpContext.Response 
      && (null == httpContext.Response.Filter 
      || !(httpContext.Response.Filter is GZipStream || httpContext.Response.Filter is DeflateStream))) 
     { 
      // Is GZip supported? 
      string acceptEncoding = httpContext.Request.Headers["Accept-Encoding"]; 
      if (null != acceptEncoding 
       && acceptEncoding.IndexOf(DecompressionMethods.GZip.ToString(), StringComparison.OrdinalIgnoreCase) >= 0) 
      { 
       httpContext.Response.Filter = new GZipStream(httpContext.Response.Filter, CompressionMode.Compress); 
       httpContext.Response.AddHeader("Content-Encoding", DecompressionMethods.GZip.ToString().ToLowerInvariant()); 
      } 
      else if (null != acceptEncoding 
       && acceptEncoding.IndexOf(DecompressionMethods.Deflate.ToString(), StringComparison.OrdinalIgnoreCase) >= 0) 
      { 
       httpContext.Response.Filter = new DeflateStream(httpContext.Response.Filter, CompressionMode.Compress); 
       httpContext.Response.AddHeader("Content-Encoding", DecompressionMethods.Deflate.ToString().ToLowerInvariant()); 
      } 

      // Allow proxy servers to cache encoded and unencoded versions separately 
      httpContext.Response.AppendHeader("Vary", "Content-Encoding"); 
     } 
    } 
} 

// Represents a bundle that does CSS minification and GZip compression. 
public sealed class GZipStyleBundle : GZipBundle 
{ 
    public GZipStyleBundle(string virtualPath, params IBundleTransform[] transforms) : base(virtualPath, transforms) { } 
} 

// Represents a bundle that does JS minification and GZip compression. 
public sealed class GZipScriptBundle : GZipBundle 
{ 
    public GZipScriptBundle(string virtualPath, params IBundleTransform[] transforms) 
     : base(virtualPath, transforms) 
    { 
     base.ConcatenationToken = ";" + Environment.NewLine; 
    } 
} 

quindi è possibile utilizzare GZipStyleBundle e GZipScriptBundle per sostituire l'originale Bundle classi : StyleBundle, ScriptBundle. Es:

public static class BundleConfig 
{ 
    // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725 
    public static void RegisterBundles(BundleCollection bundles) 
    { 
     bundles.Add(new GZipScriptBundle("~/bundles/jquery.js").Include(...)); 
     bundles.Add(new GZipScriptBundle("~/bundles/jquery-ui.js", new JsMinify()).Include(...)); 

     bundles.Add(new GZipStyleBundle("~/bundles/all.css", new CssMinify()).Include(...)); 
    } 
} 

saluti