Además de eliminar las descargas de recursos innecesarios, lo mejor que puedes hacer para mejorar la velocidad de carga de la página es minimizar el tamaño total de la descarga optimizando y comprimiendo los recursos restantes.
Introducción a la compresión de datos
Una vez que hayas configurado tu sitio web para evitar la descarga de recursos no utilizados, el siguiente paso es comprimir los recursos aptos restantes que el navegador debe descargar. Según el tipo de recurso (texto, imágenes, fuentes, etcétera), existen muchas técnicas diferentes para elegir: herramientas genéricas que se pueden habilitar en el servidor web, optimizaciones de preprocesamiento para tipos de contenido específicos y optimizaciones específicas de recursos que requieren la intervención del desarrollador.
Para ofrecer el mejor rendimiento, se requiere una combinación de todas las siguientes técnicas:
- La compresión es el proceso de codificar información con menos bits.
- Eliminar los datos innecesarios siempre produce los mejores resultados.
- Existen muchas técnicas y algoritmos de compresión diferentes.
- Necesitarás una variedad de técnicas para lograr la mejor compresión.
El proceso de reducir el tamaño de los datos se denomina compresión de datos. Muchas personas aportaron algoritmos, técnicas y optimizaciones para mejorar las proporciones de compresión, la velocidad de compresión y la memoria requerida por varios algoritmos de compresión.
Un análisis completo de la compresión de datos supera el alcance de esta guía. Sin embargo, es importante comprender, a un nivel general, cómo funciona la compresión y las técnicas que puedes usar para reducir el tamaño de los diversos recursos que requieren tus páginas.
Para ilustrar los principios básicos de estas técnicas, considera el proceso de optimización de un formato de mensaje de texto simple que se inventó solo para este ejemplo:
# Below is a secret message, which consists of a set of headers in
# key-value format followed by a newline and the encrypted message.
format: secret-cipher
date: 08/25/16
AAAZZBBBBEEEMMM EEETTTAAA
- Los mensajes pueden contener anotaciones arbitrarias, a veces denominadas comentarios, que se indican con el prefijo "#". Las anotaciones no afectan el significado del mensaje ni sus comportamientos.
- Los mensajes pueden contener encabezados, que son pares clave-valor (separados por
":"en el ejemplo anterior) que aparecen al comienzo del mensaje. - Los mensajes contienen cargas útiles de texto.
¿Qué se puede hacer para reducir el tamaño del mensaje previo, que comienza en 200 caracteres?
- El comentario es interesante, pero no afecta el significado del mensaje. Eliminarlo cuando se transmite el mensaje
- Existen buenas técnicas para codificar encabezados de manera eficiente. Por ejemplo, si sabes que todos los mensajes tienen "formato" y "fecha", podrías convertirlos en IDs de números enteros cortos y solo enviar esos. Sin embargo, es posible que no sea así, por lo que es mejor dejarlo como está por ahora.
- La carga útil solo contiene texto. Si bien no sabemos cuál es el contenido real (aparentemente, usa un
"secret-cipher"), solo con mirar el texto se observa que hay mucha redundancia. Quizás, en lugar de enviar letras repetidas, puedes contar la cantidad de letras repetidas y codificarlas de manera más eficiente. Por ejemplo,"AAA"se convierte en"3A", que representa una secuencia de tres letras A.
La combinación de estas técnicas produce el siguiente resultado:
format: secret-cipher
date: 08/25/16
3A2Z4B3E3M 3E3T3A
El mensaje nuevo tiene 56 caracteres, lo que significa que comprimiste el mensaje original en un 72%. ¡Es una reducción significativa!
Este es un ejemplo ilustrativo de cómo los algoritmos de compresión pueden ser eficaces para reducir el tamaño de transferencia de los recursos basados en texto. En la práctica, los algoritmos de compresión son mucho más sofisticados de lo que ilustra el ejemplo anterior y, en la Web, se pueden usar para reducir significativamente los tiempos de descarga de los recursos. Cuando se aplica compresión a los recursos basados en texto, una página web puede dedicar menos tiempo a cargar recursos, de modo que los usuarios puedan ver los efectos de esos recursos antes de lo que lo harían sin compresión.
Reducción: Optimizaciones específicas del contexto y procesamiento previo
La primera técnica que se analiza aquí es la minificación. Si bien la minificación no es estrictamente un algoritmo de compresión, es una forma de quitar los caracteres innecesarios y redundantes que se usan en el código fuente para que los recursos sean más legibles para los humanos. Sin embargo, esa legibilidad no es necesaria para mantener la funcionalidad de ese código fuente en los sitios web de producción y puede retrasar la carga de recursos en la Web.
La minificación es un tipo de optimización específica del contenido que puede reducir significativamente el tamaño de los recursos entregados. Estas optimizaciones se aplican mejor como parte del proceso de compilación y de implementación. Por ejemplo, los bundlers son un tipo de software de uso común que puede minimizar automáticamente los recursos justo antes de la implementación de un nuevo código de producción en un sitio web.
La mejor manera de comprimir datos redundantes o innecesarios es eliminarlos. Sin embargo, no puedes borrar datos arbitrarios. Sin embargo, en algunos contextos en los que tenemos conocimiento específico del contenido sobre el formato de los datos y sus propiedades, es posible reducir significativamente el tamaño de la carga útil sin afectar su significado o capacidades reales.
<html>
<head>
<style>
/* awesome-container is only used on the landing page */
.awesome-container {
font-size: 120%;
}
.awesome-container {
width: 50%;
}
</style>
</head>
<body>
<!-- awesome container content: START -->
<div>
This is my awesome container, and it is <em>so</em> awesome.
</div>
<!-- awesome container content: END -->
<script>
awesomeAnalytics(); // Beacon conversion metrics
</script>
</body>
</html>
Considera el fragmento de HTML anterior y los tres tipos de contenido diferentes que contiene:
- Lenguaje de marcado HTML.
- CSS para personalizar la presentación de una página
- JavaScript para potenciar las interacciones y otras capacidades avanzadas de la página
Cada uno de estos tipos de contenido tiene diferentes reglas sobre lo que constituye contenido válido, diferentes reglas para especificar comentarios, etcétera. Sin embargo, la pregunta que queda es: "¿Cómo se puede reducir el tamaño de esta página?".
- Los comentarios del código son el mejor amigo de los desarrolladores, pero el navegador no los necesita. Quitar los comentarios de CSS (
/* ... */), HTML (<!-- ... -->) y JavaScript (// ...) reduce el tamaño total de transferencia de la página y sus recursos secundarios. - Un compresor de CSS "inteligente" podría notar que estamos usando una forma ineficiente de definir reglas para
.awesome-containery contraer las dos declaraciones en una sin afectar ningún otro estilo, lo que ahorraría más bytes. En un conjunto grande de reglas de CSS, quitar este tipo de redundancia puede ser útil, pero no es algo que se pueda aplicar de forma agresiva, ya que los selectores a menudo se duplican necesariamente en diferentes contextos, como dentro de las consultas de medios. - Los espacios y las tabulaciones son comodidades para los desarrolladores en HTML, CSS y JavaScript. Un compresor adicional podría quitar todas las tabulaciones y los espacios. A diferencia de otras técnicas de deduplicación, este tipo de optimización se puede aplicar de forma bastante agresiva, siempre y cuando esos espacios o pestañas no sean necesarios para la presentación de la página. Por ejemplo, querrás conservar los espacios dentro de las ejecuciones de texto en un documento HTML, ya que garantizan la legibilidad del contenido que los usuarios verán.
<html><head><style>.awesome-container{font-size:120%;width:50%}</style></head><body><div>This is my awesome container, and it is <em>so</em> awesome.</div><script>awesomeAnalytics()</script></body></html>
Después de aplicar los pasos anteriores, la página pasa de 516 a 204 caracteres, lo que representa un ahorro de aproximadamente el 60%. Es cierto que no es muy legible, pero no es necesario que lo sea para que se pueda usar. Las prácticas de desarrollo modernas también te permiten mantener las versiones bien formateadas y legibles de tu código fuente separadas del código bien optimizado que envías a producción. En combinación con los mapas de origen, que proporcionan una representación legible del código de producción transformado, puedes solucionar errores en la producción con mayor facilidad y tener una buena experiencia del desarrollador mientras optimizas el rendimiento en beneficio de la experiencia del usuario.
El ejemplo anterior ilustra un punto importante: un compresor de uso general, por ejemplo, uno diseñado para comprimir texto arbitrario, podría hacer un trabajo bastante bueno comprimiendo la página del ejemplo anterior, pero nunca sabría cómo quitar los comentarios, contraer las reglas CSS o realizar docenas de otras optimizaciones específicas del contenido. Por eso, el preprocesamiento, la minificación y otras optimizaciones basadas en el contexto son importantes.
Del mismo modo, las técnicas descritas anteriormente se pueden extender más allá de los recursos basados en texto. Las imágenes, los videos y otros tipos de contenido contienen sus propios formularios de metadatos y varias cargas útiles. Por ejemplo, cada vez que tomas una foto con una cámara, su archivo suele incorporar mucha información adicional: parámetros de configuración de la cámara, ubicación, etcétera. Según tu aplicación, estos datos pueden ser fundamentales (por ejemplo, en un sitio para compartir fotos) o completamente inútiles. Debes considerar si vale la pena quitarlo. En la práctica, estos metadatos pueden agregar hasta decenas de kilobytes por cada imagen.
En resumen, como primer paso para optimizar la eficiencia de tus recursos, crea un inventario de los diferentes tipos de contenido y considera qué tipos de optimizaciones específicas del contenido puedes aplicar para reducir su tamaño. Luego, después de que descubras cuáles son, automatiza estas optimizaciones agregándolas a los pasos de compilación y lanzamiento para garantizar que se apliquen de manera coherente en cada lanzamiento nuevo a producción.
Compresión de texto con algoritmos de compresión
El siguiente paso para reducir el tamaño de los recursos basados en texto es aplicarles un algoritmo de compresión. Este método va un paso más allá, ya que busca de forma agresiva patrones repetibles en las cargas útiles basadas en texto antes de enviarlas al usuario y las descomprime una vez que llegan al navegador del usuario. El resultado es una reducción aún mayor y significativa de esos recursos, y tiempos de descarga más rápidos.
- gzip y Brotli son algoritmos de compresión de uso común que funcionan mejor en los recursos basados en texto: CSS, JavaScript y HTML.
- Todos los navegadores modernos admiten la compresión gzip y Brotli, y anunciarán la compatibilidad con ambos en el encabezado de la solicitud HTTP
Accept-Encoding. - Tu servidor debe estar configurado para habilitar la compresión. El software del servidor web suele habilitar módulos para comprimir recursos basados en texto de forma predeterminada.
- Tanto gzip como Brotli se pueden ajustar para mejorar las relaciones de compresión ajustando el nivel de compresión. En el caso de gzip, la configuración de compresión varía de 1 a 9, siendo 9 la mejor. En el caso de Brotli, este rango es de 0 a 11, y 11 es el mejor. Sin embargo, los parámetros de configuración de compresión más altos requieren más tiempo. En el caso de los recursos que se comprimen de forma dinámica, es decir, en el momento de la solicitud, los parámetros de configuración en el medio del rango tienden a ofrecer la mejor compensación entre el índice de compresión y la velocidad. Sin embargo, es posible la compresión estática, que se produce cuando la respuesta se comprime con anticipación y, por lo tanto, puede usar la configuración de compresión más agresiva disponible para cada algoritmo de compresión.
- Las redes de distribución de contenidos (CDN) suelen ofrecer compresión automática de los recursos aptos. Las CDN también pueden administrar la compresión dinámica y estática por ti, lo que te quita una preocupación más sobre la compresión.
gzip y Brotli son compresores comunes que se pueden aplicar a cualquier flujo de bytes. Internamente, recuerdan parte del contenido examinado previamente de un archivo y, luego, intentan encontrar y reemplazar fragmentos de datos duplicados de manera eficiente.
En la práctica, tanto gzip como Brotli funcionan mejor con el contenido basado en texto, y suelen alcanzar tasas de compresión de hasta el 70% o el 90% para archivos más grandes. Sin embargo, ejecutar estos algoritmos en recursos que ya están comprimidos con algoritmos alternativos (como la mayoría de los formatos de imagen que usan técnicas de compresión con o sin pérdida) no genera ninguna mejora o genera una mejora mínima.
Todos los navegadores modernos anuncian la compatibilidad con gzip y Brotli en el encabezado de la solicitud HTTP Accept-Encoding. Sin embargo, es responsabilidad del proveedor de hosting garantizar que el servidor web esté configurado correctamente para entregar el recurso comprimido cuando el cliente lo solicite.
| Archivo | Algoritmo | Tamaño sin comprimir | Tamaño comprimido | Índice de compresión |
|---|---|---|---|---|
| angular-1.8.3.js | Brotli | 1,346 KiB | 256 KiB | 81% |
| angular-1.8.3.js | gzip | 1,346 KiB | 329 KiB | 76% |
| angular-1.8.3.min.js | Brotli | 173 KiB | 53 KiB | 69% |
| angular-1.8.3.min.js | gzip | 173 KiB | 60 KiB | 65% |
| jquery-3.7.1.js | Brotli | 302 KiB | 69 KiB | 77% |
| jquery-3.7.1.js | gzip | 302 KiB | 83 KiB | 73% |
| jquery-3.7.1.min.js | Brotli | 85 KiB | 27 KiB | 68% |
| jquery-3.7.1.min.js | gzip | 85 KiB | 30 KiB | 65% |
| lodash-4.17.21.js | Brotli | 531 KiB | 73 KiB | 86% |
| lodash-4.17.21.js | gzip | 531 KiB | 94 KiB | 82% |
| lodash-4.17.21.min.js | Brotli | 71 KiB | 23 KiB | 68% |
| lodash-4.17.21.min.js | gzip | 71 KiB | 25 KiB | 65% |
En la tabla anterior, se muestran los ahorros que pueden proporcionar la compresión Brotli y gzip para algunas bibliotecas de JavaScript conocidas. Los ahorros oscilan entre el 65% y el 86%, según el archivo y el algoritmo. Como referencia, se aplicó el nivel de compresión máximo a cada archivo para Brotli y gzip. Siempre que sea posible, prefiere Brotli en lugar de gzip.
Habilitar la compresión es una de las optimizaciones más sencillas y eficaces que se pueden implementar. Si tu sitio web no la aprovecha, estás perdiendo una gran oportunidad para mejorar el rendimiento para tus usuarios. Afortunadamente, muchos servidores web proporcionan configuraciones predeterminadas que habilitan esta importante optimización, y las CDN en particular son muy eficaces para implementarla de una manera que equilibre la velocidad y la proporción de compresión.
Una forma rápida de ver la compresión en acción es abrir las Herramientas para desarrolladores de Chrome, abrir el panel Red, cargar una página de tu elección y observar la parte inferior del panel de red.
Al igual que en la imagen anterior, deberías ver un desglose de lo siguiente:
- Es la cantidad de solicitudes, que es la cantidad de recursos cargados para la página.
- El tamaño de transferencia de todas las solicitudes. Esto refleja la eficacia de la compresión aplicada a cualquiera de los recursos de una página.
- El tamaño del recurso de todas las solicitudes. Esto refleja el tamaño de los recursos de la página después de que se descomprimieron.
Efectos en las Métricas web esenciales
Las mejoras en el rendimiento no se pueden medir a menos que haya métricas que las reflejen. La iniciativa de Métricas web esenciales tiene como objetivo crear y dar a conocer las métricas que reflejan la experiencia real del usuario. Esto contrasta con las métricas, como el tiempo de carga de la página, que no se traducen claramente en la calidad de la experiencia del usuario.
Cuando apliques las optimizaciones que se describen en esta guía a los recursos de tu sitio web, los efectos en Core Web Vitals pueden variar según los recursos optimizados y las métricas involucradas. Sin embargo, estos son algunos casos en los que aplicar estas optimizaciones puede mejorar las Core Web Vitals de tu sitio web:
- Los recursos HTML que se minimizan y comprimen pueden mejorar la carga de ese HTML, la visibilidad de sus subrecursos y, por lo tanto, mejorar la carga de estos. Esto puede ser beneficioso para el Largest Contentful Paint (LCP) de una página. Si bien las sugerencias de recursos, como
rel="preload", se pueden usar para afectar la capacidad de detección de los recursos, usar demasiadas puede causar problemas con la contención del ancho de banda. Si te aseguras de que la respuesta HTML para una solicitud de navegación esté comprimida, el analizador de carga previa podrá descubrir los recursos que contiene lo antes posible. - Algunos candidatos a LCP también se pueden cargar antes con la compresión. Por ejemplo, la duración de carga de recursos de las imágenes SVG que son candidatas a LCP se puede reducir a través de la compresión basada en texto. Esto es diferente de las optimizaciones que realizarías en otros tipos de imágenes, que se comprimen de forma intrínseca a través de otros métodos de compresión, como la forma en que las imágenes JPEG usan la compresión con pérdida.
- Además, los nodos de texto también pueden ser candidatos a LCP. La forma en que se aplican las técnicas descritas en esta guía depende de si usas una fuente web para el texto de tus páginas web. Si usas una fuente web, se aplican las prácticas recomendadas de optimización de fuentes web. Sin embargo, si no usas fuentes web, sino fuentes del sistema que se muestran sin incurrir en ninguna duración de carga de recursos, la minificación y la compresión de tu CSS reducen esta duración, lo que significa que la renderización de los posibles nodos de texto del LCP puede ocurrir antes.
Conclusión
La forma en que optimizas la codificación y la transferencia de recursos basados en texto es un concepto de rendimiento básico, pero tiene un gran impacto. Asegúrate de hacer todo lo posible para garantizar que los recursos aptos para la minificación y la compresión se beneficien de esas optimizaciones.
Y lo que es más importante, asegúrate de que estos procesos se automaticen. Para la minificación, usa un bundler para aplicar la minificación a los recursos aptos. Asegúrate de que la configuración de tu servidor web admita la compresión, pero, más que eso, usa la compresión más eficaz disponible. Para que esto sea lo más trivial posible, usa CDN para automatizar la compresión, ya que no solo pueden comprimir recursos, sino que también pueden hacerlo muy rápido.
Si consolidas estos conceptos de rendimiento de referencia en la arquitectura de tu sitio web, puedes asegurarte de que tus esfuerzos de optimización del rendimiento se basen en una buena base y de que las optimizaciones posteriores se puedan basar en una base sólida de buenas prácticas de referencia.