Problemas clave de rendimiento

En la actualidad, las imágenes son los recursos más importantes de la Web en términos del tamaño total de transferencia y la cantidad de solicitudes por página. El tamaño de transferencia total de la página web mediana es de aproximadamente 2 MB a partir de junio de 2022, y solo las imágenes representan casi la mitad de ese tamaño. No es exagerado decir que optimizar las solicitudes de imágenes puede ser la única optimización de rendimiento más grande que puedes hacer.

Más adelante, aprenderás cómo evolucionaron las imágenes responsivas para ayudar con los problemas que se crearon al intentar entregar una imagen para todas las eventualidades. En esta sección, descubrirás las métricas clave de rendimiento relacionadas con las imágenes y cómo mejorarlas.

Cómo aplazar solicitudes de imágenes

Si bien estás a punto de aprender varias formas de garantizar que tus solicitudes de imágenes sean lo más pequeñas y eficientes posible, la solicitud de imagen más rápida siempre será la que nunca se realice. Por lo tanto, quiero mostrarte cuál es el cambio de mayor impacto que puedes hacer en la forma en que entregas los recursos de imagen a los usuarios: el atributo loading="lazy".

<img src="image.jpg" loading="lazy" alt="…">

Este atributo garantiza que las solicitudes de imágenes no se realicen hasta que se acerquen al viewport del usuario, lo que las difiere de la carga de la página inicial (el momento en que el navegador está más activo) y quita esas solicitudes de la ruta de renderización crítica.

Por más simple que sea en la práctica, el uso de este atributo puede tener un gran impacto positivo en el rendimiento: nunca se solicitará una imagen que nunca quede en el viewport del usuario y no se desperdiciará ancho de banda en imágenes que el usuario nunca verá.

Sin embargo, hay un problema: aplazar esas solicitudes significa no aprovechar los procesos hiperoptimizados de los navegadores para solicitar imágenes lo antes posible. Si se usa loading="lazy" en elementos img en la parte superior del diseño y, por lo tanto, es más probable que se encuentren en el viewport del usuario cuando se carga la página por primera vez, el usuario final podría sentir que estas imágenes son mucho más lentas.

Prioridad de recuperación

El atributo loading es un ejemplo de un esfuerzo mayor por los estándares web para brindarles a los desarrolladores más poder sobre la forma en que los navegadores web priorizan las solicitudes.

Es probable que conozcas los enfoques básicos para recuperar la prioridad de los navegadores: por ejemplo, una solicitud de un archivo CSS externo en la <head> de un documento se considera lo suficientemente esencial para bloquear la renderización, mientras que una solicitud de un archivo JavaScript externo que tiene un valor superior a </body> se aplazará hasta que se complete la renderización. Si el valor de un atributo loading de un <img> es "diferido", la solicitud de imagen asociada se diferirá hasta que el navegador determine que se mostrará a un usuario. De lo contrario, esa imagen tendrá la misma prioridad que cualquier otra imagen de la página.

El atributo fetchpriority está diseñado para brindarles a los desarrolladores un control más detallado sobre la prioridad de los elementos, lo que te permite marcar los recursos como de prioridad "alta" y "baja" en relación con los recursos del mismo tipo. Los casos de uso de fetchpriority son similares a los del atributo loading, aunque mucho más amplios. Por ejemplo, puedes usar fetchpriority="low" en una imagen que solo se muestre después de la interacción del usuario (ya sea que esté dentro del viewport del usuario o no) para priorizar las imágenes visibles en otra parte de la página, o fetchpriority="high" para priorizar una imagen que sabes que será visible de inmediato en el viewport en cuanto se renderice la página.

Ten en cuenta que fetchpriority es diferente de loading en que no cambia fundamentalmente el comportamiento del navegador. No le indica al navegador que cargue ciertos recursos antes que otros, sino que le brinda un contexto fundamental para las decisiones que toma cuando se solicitan recursos.

Mide el impacto de las imágenes

Cuando se optimizan los elementos de imagen, el rendimiento percibido suele ser más importante y difícil de medir que el tamaño total de transferencia solo.

Las Métricas web proporcionan métricas y orientación medibles y prácticas para mejorar la experiencia de los usuarios en la Web y destacan problemas como el tiempo de respuesta lento de un servidor web, los problemas de renderización y los retrasos en la interactividad. Las Métricas web esenciales son un subconjunto de estos objetivos, que se enfocan en la experiencia directa del usuario en una página individual, un conjunto de mediciones técnicas que, en conjunto, determinan qué tan rápida se siente para un usuario.

Cambio de diseño acumulado

El Cambio de diseño acumulado (CLS) es una medida de la estabilidad visual. Es una métrica que captura cuánto cambia el diseño del contenido de una página a medida que se cargan los recursos y se renderiza la página. Cualquier persona que haya pasado mucho tiempo usando la Web perdió su lugar en una larga serie de textos debido a que una página "salte" porque una fuente web o una fuente de imagen retrasada se renderiza de repente, o se alejó repentinamente de un elemento interactivo de tu puntero. Un CLS alto es una molestia en el mejor de los casos y una causa del error del usuario en el peor: un botón "Cancelar" que cambia a un espacio que antes ocupaba un botón "Confirmar", justo cuando el usuario hace clic, por ejemplo.

Debido a los altos tiempos de carga y la cantidad de espacio que pueden ocupar en un diseño, es lógico que las imágenes sean una causa común de puntuaciones altas de CLS.

Gracias a los cambios relativamente recientes en los navegadores modernos, es más fácil de lo que crees evitar las puntuaciones de CLS altas debido a las imágenes.

Si llevas algunos años trabajando en el frontend, ya estarás familiarizado con los atributos width y height en <img>: antes de la adopción generalizada de CSS, estos eran la única manera de controlar el tamaño de una imagen.

<img src="image.jpg" height="200" width="400" alt="…">

Estos atributos dejaron de usarse en un esfuerzo por mantener nuestras preocupaciones de estilo separadas de nuestro lenguaje de marcado, especialmente porque el diseño web responsivo hizo necesario especificar el tamaño basado en porcentajes a través de CSS. En los primeros días del diseño web responsivo, "quitar los atributos width y height sin usar" era un consejo común, ya que los valores que especificamos en nuestro CSS (max-width: 100% y height: auto) los anularían.

<img src="image.jpg" alt="…">
img {
  max-width: 100%;
  height: auto;
}

Después de quitar los atributos height y width como en el ejemplo anterior, el único método que tiene el navegador para determinar la altura de la imagen en esta situación es solicitar la fuente, analizarla y renderizarla con su relación de aspecto intrínseca, según el ancho del espacio que ocupa en el diseño una vez que se aplicaron las hojas de estilo. Gran parte de este proceso se lleva a cabo después de la renderización de la página, y la altura recién calculada genera cambios de diseño adicionales.

A partir de 2019, se actualizó el comportamiento del navegador para controlar los atributos width y height de manera diferente. En lugar de usar los valores de estos atributos para determinar el tamaño fijo basado en píxeles de un elemento img en el diseño, se puede pensar que estos atributos representan la relación de aspecto de la imagen, aunque la sintaxis es la misma. Los navegadores modernos dividirán estos valores entre sí para determinar la relación de aspecto intrínseca de un elemento img antes de que se renderice la página, lo que le permitirá reservar el espacio que ocupará la imagen cuando se renderice el diseño.

Como regla general, siempre debes usar los atributos height y width en <img>, con valores que coincidan con el tamaño intrínseco de la fuente de la imagen, siempre que te asegures de especificar height: auto junto con max-width: 100% para anular la altura del atributo HTML.

<img src="image.jpg" height="200" width="400" alt="…">
img {
  max-width: 100%;
  height: auto;
}

Si usas los atributos width y height en tus elementos <img>, evitarás una puntuación de CLS alta debido a las imágenes.

Es importante tener en cuenta que este enfoque no presenta desventajas, ya que se basa en el comportamiento de navegador establecido desde hace tiempo: cualquier navegador compatible con CSS básico funcionará como siempre, y los atributos height y width del lenguaje de marcado anulan los estilos.

Si bien los atributos width y height evitan fácilmente los problemas de CLS, ya que reservan el espacio de diseño necesario para tus imágenes, no es lo ideal presentar a los usuarios un espacio vacío o un marcador de posición de baja calidad mientras esperan a que se transfiera y renderice una imagen. Si bien puedes realizar acciones para mitigar el impacto medible y perceptible de las imágenes de carga lenta, la única forma de presentar una imagen completamente renderizada a un usuario con mayor rapidez es reducir su tamaño de transferencia.

Procesamiento de imagen con contenido más grande

La métrica Largest Contentful Paint (LCP) mide el tiempo que lleva renderizar el elemento “con contenido” más grande visible en el viewport del usuario, es decir, el elemento de contenido que ocupa el mayor porcentaje de la página visible. Puede parecer una métrica demasiado específica a primera vista, pero ese elemento sirve como un proxy práctico para el punto en el que se renderizó la mayor parte de la página, desde la perspectiva del usuario. El LCP es una medida vital del rendimiento (percibido).

Las métricas como DOMContentLoaded o el evento window.onload pueden ser útiles para determinar cuándo se completó técnicamente el proceso de carga de la página actual, pero no corresponden necesariamente a la experiencia de un usuario en la página. Una leve demora en la renderización de un elemento fuera del viewport del usuario se incluiría en cualquiera de estas métricas, pero es probable que un usuario real no la detecte por completo. Un LCP largo significa que la primera impresión del usuario de una página (el contenido más importante dentro del viewport actual) es que la página es lenta o está completamente dividida.

La percepción del usuario capturada por el LCP tiene un impacto directo en la experiencia del usuario. En un experimento realizado por Vodafone el año pasado, se descubrió que una mejora del 31% en el LCP no solo generaba un 8% más de ventas (un resultado sólido por sí solo), sino que la cantidad total de usuarios mejoró un 15% en la cantidad de visitantes que se convirtieron en clientes potenciales ("tasa de visitante a cliente potencial") y una mejora del 11% en la cantidad de usuarios que visitaron su carrito ("tasa de carrito").

En más del 70% de las páginas web, el elemento más grande del viewport inicial involucra una imagen, ya sea como un elemento <img> independiente o como un elemento con una imagen de fondo. En otras palabras, el 70% de las puntuaciones de LCP de las páginas se basan en el rendimiento de la imagen. No se necesita mucha imaginación para entender el motivo: es muy probable que las imágenes y los logotipos grandes y llamativos se encuentren en la "mitad superior de la página".

LCP destacado en la consola de una página web.dev

A continuación, se indican algunos pasos que puedes seguir para evitar las demoras en el LCP: primero, nunca especifiques loading="lazy" en una imagen de la "mitad superior de la página", ya que retrasar la solicitud hasta que se procese la página tendrá un impacto negativo masivo en tu puntuación de LCP. En segundo lugar, usar fetchpriority="high" puede informar al navegador que la transferencia de esta imagen debe priorizarse por sobre las imágenes en otras partes de la página.

Con esas reglas en mente, lo más importante que puedes hacer para mejorar la puntuación de LCP de una página es reducir el tiempo que lleva transferir y renderizar esas imágenes. Para ello, deberás mantener las fuentes de imagen lo más pequeñas y eficientes posible (sin sacrificar su calidad, por supuesto), y asegurarte de que los usuarios solo obtengan los recursos de imagen que sean más adecuados para sus contextos de navegación.

Conclusión

Los recursos de imagen generan el mayor gasto en el ancho de banda de tus usuarios, es decir, el ancho de banda que se quita de la transferencia de todos los demás recursos necesarios para renderizar una página. Las imágenes presentan problemas significativos en términos de rendimiento percibido, tanto durante como después de la renderización de la página en la que se encuentra. En resumen, los recursos de imagen dañan.

Aunque puede ser abrumador, si bien "la Web sería mejor con menos imágenes" sería cierto solo en términos de rendimiento, también sería un gran perjuicio para los usuarios. Las imágenes son una parte vital de la Web, y la calidad del contenido significativo no se pone en riesgo el rendimiento exclusivo.

En el resto de este curso, aprenderás sobre las tecnologías que impulsan nuestros recursos de imagen y las técnicas para mitigar sus impactos en el rendimiento, sin comprometer la calidad.