Optimiza la codificación y el tamaño de transferencia de los recursos de texto

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 general de la descarga optimizando y comprimiendo los recursos restantes.

Conceptos básicos de la compresión de datos

Una vez que hayas configurado tu sitio web para evitar que se descarguen 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), hay muchas técnicas diferentes para elegir: herramientas genéricas que se pueden habilitar en el servidor web, optimizaciones de procesamiento previo para tipos de contenido específicos y optimizaciones específicas de recursos que requieren la entrada del desarrollador.

Para obtener el mejor rendimiento, se requiere una combinación de todas las técnicas siguientes:

  • 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 han aportado algoritmos, técnicas y optimizaciones para mejorar las proporciones y la velocidad de compresión, así como la memoria que requieren varios algoritmos de compresión.

Un análisis completo de la compresión de datos está fuera del alcance de esta guía. Sin embargo, es importante comprender, a grandes rasgos, 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
  1. 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.
  2. Los mensajes pueden contener encabezados, que son pares clave-valor (separados por ":" en el ejemplo anterior) que aparecen al principio del mensaje.
  3. Los mensajes llevan cargas útiles de texto.

¿Qué se puede hacer para reducir el tamaño del mensaje anterior, que comienza en 200 caracteres?

  1. El comentario es interesante, pero no afecta el significado del mensaje. Elimínalo cuando transmitas el mensaje.
  2. Existen buenas técnicas para codificar encabezados de manera eficiente. Por ejemplo, si sabes que todos los mensajes tienen "formato" y "fecha", puedes convertirlos en IDs de números enteros cortos y solo enviar esos. Sin embargo, es posible que eso no sea cierto, por lo que es mejor no modificarlo por ahora.
  3. La carga útil solo es texto. Si bien no sabemos cuál es su contenido real (al parecer, usa un "secret-cipher"), con solo mirar el texto se puede ver que hay mucha redundancia en él. Tal vez, 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%. Esa es una reducción significativa.

Este es un ejemplo sencillo 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. Si 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: Procesamiento previo y optimizaciones específicas del contexto

La primera técnica que se analiza aquí es la reducción. Si bien la reducción no es estrictamente un algoritmo de compresión, es una forma de quitar 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 reducción es un tipo de optimización específica del contenido que puede disminuir significativamente el tamaño de los recursos entregados, y las optimizaciones se aplican mejor como parte de tu proceso de compilación e implementación. Por ejemplo, los empaquetadores son un tipo de software de uso general que puede minificar recursos de forma automática justo antes de la implementación de un código de producción nuevo 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 del formato de datos y sus propiedades, es posible reducir significativamente el tamaño de la carga útil sin afectar su significado o sus 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 incluye:

  1. Lenguaje de marcado HTML
  2. CSS para personalizar la presentación de una página
  3. JavaScript para potenciar las interacciones y otras funciones avanzadas de la página

Cada uno de estos tipos de contenido tiene reglas diferentes para lo que constituye contenido válido, reglas diferentes 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 de código son el mejor amigo de un desarrollador, 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 subrecursos.
  • Un compresor de CSS "inteligente" podría notar que estamos usando una forma ineficiente de definir reglas para .awesome-container y contraer las dos declaraciones en una sin afectar ningún otro estilo, lo que ahorra más bytes. En un conjunto grande de reglas de CSS, quitar este tipo de redundancia puede ser útil, pero es posible que no se pueda aplicar de forma agresiva, ya que los selectores suelen duplicarse necesariamente en diferentes contextos, como en las consultas de medios.
  • Los espacios y las tabulaciones son útiles para los desarrolladores en HTML, CSS y JavaScript. Un compresor adicional podría quitar todas las pestañas y los espacios. A diferencia de otras técnicas de desduplicación, este tipo de optimización se puede aplicar de forma bastante agresiva, siempre que esos espacios o tabulaciones 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 realmente.
<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 legibles y con un formato correcto de tu código fuente separadas del código bien optimizado que envías a producción. Si se combina con mapas de origen, que proporcionan una representación legible de tu código de producción transformado, puedes solucionar problemas en producción con mayor facilidad, tener una buena experiencia de desarrollador y, al mismo tiempo, optimizar el rendimiento para mejorar la experiencia del usuario.

En el ejemplo anterior, se ilustra un punto importante: un compresor de uso general, por ejemplo, uno diseñado para comprimir texto arbitrario, podría hacer un buen trabajo comprimiendo la página del ejemplo anterior, pero nunca sabría quitar los comentarios, contraer las reglas de CSS o realizar decenas de otras optimizaciones específicas del contenido. Por este motivo, el procesamiento previo, la reducción y otras optimizaciones adaptadas al 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 incluyen sus propias formas 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, como la configuración de la cámara, la ubicación, etcétera. Según tu aplicación, estos datos pueden ser fundamentales (por ejemplo, un sitio para compartir fotos) o completamente inútiles. Deberías 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 de contenido puedes aplicar para reducir su tamaño. Luego, después de que hayas descubierto cuáles son, automatiza estas optimizaciones agregándolas a tus pasos de compilación y lanzamiento para asegurarte de que se apliquen de forma coherente en cada nueva versión de 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. Esto va un paso más allá, ya que busca de forma agresiva patrones repetibles en 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 adicional y significativa de esos recursos y, por consiguiente, tiempos de descarga más rápidos.

  • gzip y Brotli son algoritmos de compresión de uso general que funcionan mejor en 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 ambas 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 proporciones de compresión ajustando el nivel de compresión. Para gzip, los parámetros de configuración de compresión varían de 1 a 9, siendo 9 el mejor. Para Brotli, este rango es de 0 a 11, donde 11 es el mejor. Sin embargo, los parámetros 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 suelen ofrecer el mejor equilibrio entre la proporción de compresión y la velocidad. Sin embargo, es posible la compresión estática, que es 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 que cumplen con los requisitos. Las CDN también pueden administrar la compresión dinámica y estática por ti, lo que te da un aspecto menos de la compresión del que preocuparte.

gzip y Brotli son compresores comunes que se pueden aplicar a cualquier flujo de bytes. De forma interna, recuerdan algunos de los contenidos de un archivo que se examinaron antes y, luego, intentan encontrar y reemplazar los fragmentos de datos duplicados de manera eficiente.

En la práctica, tanto gzip como Brotli tienen un mejor rendimiento en el contenido basado en texto, ya que suelen alcanzar tasas de compresión de hasta un 70% a un 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, genera pocas o ninguna mejora.

Todos los navegadores actualizados anuncian la compatibilidad con gzip y Brotli en el encabezado de la solicitud HTTP Accept-Encoding. Sin embargo, es responsabilidad del proveedor de hosting asegurarse de 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 Proporción 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 las compresiones Brotli y gzip para algunas bibliotecas de JavaScript conocidas. Los ahorros varían del 65% al 86% según el archivo y el algoritmo. Como referencia, se aplicó el nivel máximo de compresión 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 puedes implementar. Si tu sitio web no lo aprovecha, te estás perdiendo una gran oportunidad de mejorar el rendimiento para tus usuarios. Afortunadamente, muchos servidores web proporcionan parámetros de configuración predeterminados que habilitan esta optimización importante, 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.

Lectura de las Herramientas para desarrolladores del tamaño real en comparación con el tamaño de transferencia.
Una representación del tamaño de transferencia (es decir, comprimido) de todos los recursos de la página en comparación con su tamaño real, como se visualiza en el panel de red de las Herramientas para desarrolladores de Chrome.

Al igual que en la imagen anterior, deberías ver un desglose de lo siguiente:

  • 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 de rendimiento no se pueden medir, a menos que haya métricas que reflejen esas mejoras. La iniciativa Core Web Vitals existe para crear y dar a conocer métricas que reflejen la experiencia real del usuario. Esto contrasta con las métricas, como el tiempo de carga de la página simple, por ejemplo, que no se traducen claramente en la calidad de la experiencia del usuario.

Cuando aplicas 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 Métricas web esenciales de tu sitio web:

  • Los recursos HTML que se reducen y comprimen pueden mejorar la carga de ese HTML, la visibilidad de sus recursos secundarios y, por lo tanto, mejorar su carga. Esto puede ser beneficioso para el Largest Contentful Paint (LCP) de una página. Si bien se pueden usar sugerencias de recursos, como rel="preload", para afectar la visibilidad de los recursos, usar demasiadas puede causar problemas con la contención del ancho de banda. Si te aseguras de que la respuesta HTML de una solicitud de navegación esté comprimida, el analizador de precarga podrá descubrir los recursos que contiene lo antes posible.
  • Algunos candidatos de LCP también se pueden cargar antes con la compresión. Por ejemplo, las imágenes SVG que son candidatas para el LCP pueden tener su duración de carga de recursos reducida a través de la compresión basada en texto. Esto es diferente de las optimizaciones que harí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 las imágenes JPEG que usan compresión con pérdida.
  • Además, los nodos de texto también pueden ser candidatos para el 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 para la 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, reducir y comprimir tu CSS reduce esta duración, lo que significa que la renderización de los posibles nodos de texto de 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 reducció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 reducción, usa un empaquetador que aplique la reducción a los recursos aptos. Asegúrate de que la configuración de tu servidor web admita la compresión, pero, además, usa la compresión más eficaz disponible. Para que esto sea lo más sencillo posible, usa CDN para automatizar la compresión, ya que no solo pueden comprimir recursos por ti, sino que también pueden hacerlo muy rápido.

Si consolidas estos conceptos de rendimiento de referencia en la arquitectura de tu sitio web, podrás asegurarte de que tus esfuerzos de optimización del rendimiento estén bien encaminados y de que las optimizaciones posteriores se basen en una base sólida de buenas prácticas de referencia.