
Un aspecto fundamental que deben cumplir nuestras aplicaciones es la rapidez con la que la página es descargada por parte del cliente. Este aspecto creo que en la actualidad cobra aun más importancia si cabe, teniendo cuenta que ya casi el 50% de los accesos se hacen desde dispositivo móvil y la mayoría con una conexión 3G. Esto provoca que ahorrar en la carga de la página KBs de descarga cobre una vital importancia en nuestros proyectos.
GZIP
La compresión por GZIP es una de las posibilidades más importantes para optimizar un sitio web, y con ello, minimizar la carga de las páginas. Consiste en enviar los archivos del sitio en formato comprimido, para que ocupen mucho menos espacio y por tanto se transfieran por la red de una manera más rápida.
Es decir, la principal ventaja de comprimir con GZIP los archivos de nuestra aplicación web es que será menos pesada en KBs y por este motivo:
- Ahorro de ancho de banda / transferencia: Nuestro sitio web enviará archivos comprimidos y por tanto, la transferencia que utilizará para enviar una misma página, será mucho menor que si no estuviera comprimida. Se obtendrá un ahorro considerable en transferencia y en su capacidad para servir más peticiones a la vez.
- Velocidad del sitio: Los archivos comprimidos, pesan menos, y por tanto tardarán menos en llegar a sus destinatarios, por lo que el sitio cargará con mayor rapidez.
- Soporte en todos los navegadores actuales: Todos los navegadores actuales son capaces de implementar GZIP.
Bundles de ASP MVC
Desde ASP.NET MVC 4 tenemos disponible la característica de los Bundles. Destacar que Bundle, en Internet, es simplemente una agrupación lógica de archivos que se pueden referenciar mediante un único nombre, y que se cargan en una única petición HTTP.
El paquete Bundles de ASP MVC principalmente se encarga de minification and bundling (también denominada Web Optimization), que permite compactar y agrupar archivos de Javascript y CSS en nuestra aplicación web. Esta característica es proporcionada por la librería System.Web.Optimization, que tenemos disponible en los proyectos desde ASP.NET MVC 4.
Sus dos objetivos principales:
- La agrupación (bundling) generalmente incluye uno o más archivos de scripts JS o CSS relacionados entre sí. Estos archivos son compactados y optimizados permitiéndonos descargarlos por única vez del servidor ahorrándonos varias peticiones o request.
- La compactación (monification) se realiza en el server y ocurre una única vez, este proceso elimina todos los espacios y saltos de líneas de los archivos incluidos en el paquete (bundle), ademas de renombrar todas las variables por nombres muchos más simples y pequeños. El resultado final: archivos muchos más livianos que ofrecen una mejor performance en el cliente.
Por tanto, usar Bundles en nuestros proyectos de ASP MVC .NET es muy importante por su función de optimizar las aplicaciones web.
Como aplicar GZIP en los Bundles de ASP MVC
Como ya hemos comentado, el objetivo principal de los Bundles en ASP MVC es optimizar la aplicación web, pero… se puede mejorar!!! ¿Cómo? Aplicando el concepto de compresión GZip junto al de Bundles.
De esta manera, tendré mis archivos CSS/Javascript agrupados y compactados (por Bundles) y además, el resultado obtenido, comprimido en GZip para que ocupe el mínimo espacio posible.
Solo necesitamos añadir a nuestro proyecto 3 clases. La primera es de donde heredaran las otras dos, y donde se define la cabecera GZip para que los navegadores puedan interpretarla en sus requests.
[code language=”csharp”]
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");
}
}
}
[/code]
Los dos bundles que usaremos en nuestros proyectos:
[code language=”csharp”]
public sealed class GZipScriptBundle : GZipBundle
{
public GZipScriptBundle(string virtualPath, params IBundleTransform[] transforms)
: base(virtualPath, transforms)
{
base.ConcatenationToken = ";" + Environment.NewLine;
}
}
[/code]
Y el StyleBundle:
[code language=”csharp”]
public sealed class GZipStyleBundle : GZipBundle
{
public GZipStyleBundle(string virtualPath, params IBundleTransform[] transforms) : base(virtualPath, transforms) { }
}
[/code]
Ahora ya solo es necesario usarlas en el BundleConfig:
[code language=”csharp”]
public static class BundleConfig
{
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(…));
}
}
[/code]
Resultados
* No os fijéis mucho en el peso y tiempos de carga. Depende del navegador, y por otra parte la página sobre la que he realizado el ejemplo tiene imágenes que se cargan aleatoriamente, y distorsionan un poco los resultados de carga final, aún así podéis ver que se ven las diferencias.
Podéis hacer un análisis de optimización de carga de vuestra página en: http://gtmetrix.com/
Sin Bundles y sin GZip
Con Bundles pero sin GZip
Con Bundles y con GZip
Javi Giner
Latest posts by Javi Giner (see all)
- IIS Express Visual Studio, como configurar para permitir conexiones remotas - febrero 26, 2016
- Evento solidario sobre Innovación - diciembre 14, 2015
- Uso de Component en Unity - noviembre 10, 2015