Hace poco más de un año, el equipo de Chrome Aurora lanzó la directiva NgOptimizedImage de Angular. La directiva se enfoca principalmente en mejorar el rendimiento, según lo miden las métricas de las Métricas web esenciales. Combina optimizaciones de imágenes comunes y prácticas recomendadas en una API para usuarios que no es mucho más complicada que un elemento <img>
estándar.
En 2023, mejoramos la directiva con funciones nuevas. En esta publicación, se describe la más sustancial de esas funciones nuevas, con énfasis en por qué elegimos priorizar cada función y cómo puede ayudar a mejorar el rendimiento de las aplicaciones de Angular.
Nuevas funciones
NgOptimizedImage mejoró sustancialmente con el tiempo, incluidas las siguientes funciones nuevas.
Modo de relleno
Proporcionar un atributo width
y height
para cambiar el tamaño de tus imágenes es una optimización extremadamente importante para reducir el desplazamiento del diseño, ya que los navegadores necesitan conocer la relación de aspecto de la imagen para ahorrar espacio para ella. Sin embargo, el ajuste del tamaño de las imágenes es un trabajo adicional para los desarrolladores de aplicaciones y no tiene sentido en algunos casos de uso de imágenes.
La primera función principal que se agregó al componente de imagen después de la vista previa para desarrolladores ayuda a resolver esta tensión: el modo de relleno. Esta es una forma para que los desarrolladores incluyan imágenes sin definir su tamaño de forma explícita y sin incurrir en un cambio de diseño.
Con el modo de relleno, se inhabilita el requisito de tamaño de la imagen y se le aplica un diseño automáticamente para que ocupe todo el elemento que la contiene. Esto desvincula la relación de aspecto de una imagen del espacio que ocupa en la página y te brinda un mayor control sobre cómo se ajustan las imágenes en el diseño de la página.
El modo de relleno usa NgOptimizedImage como una alternativa de mejor rendimiento a la propiedad css background-image
. Coloca una imagen dentro de <div>
o algún otro elemento que tendría el diseño de background-image
y, luego, habilita el modo de relleno, como se muestra en el ejemplo de código anterior. Usa las propiedades CSS object-fit
y object-position
en <div>
para controlar cómo se posiciona la imagen en segundo plano.
// Height and width are required
<img ngSrc="example.com" height="300" width="400">
// Unless you use fill mode!
<div style="width: 100vw; height: 50em; position: relative">
<img ngSrc="example.com" fill>
</div>
Generación de srcset
Una de las técnicas de optimización de imágenes más eficaces es el uso del atributo srcset
para garantizar que se descarguen imágenes del tamaño adecuado para cualquier dispositivo que acceda a tu aplicación. El uso de srcset
en toda tu app puede evitar que desperdicies ancho de banda y mejorar sustancialmente tu Métrica web esencial de LCP.
La desventaja del atributo srcset
es que puede ser engorroso de implementar. Escribir los valores de srcset
de forma manual significa agregar varias líneas de marcado a cada elemento de imagen de tu app, con varias URLs personalizadas para cada srcset
. También debes decidir un conjunto de puntos de inflexión, lo que es complicado, ya que pueden representar tanto las densidades de pantalla como los tamaños de viewport de dispositivos comunes.
Por eso, agregar la generación automática de srcset a la directiva NgOptimizedImage fue un gran logro posterior al lanzamiento. Con esta incorporación, cualquier aplicación que use una CDN que admita el cambio de tamaño de las imágenes puede obtener srcsets completos y personalizables que se agregan automáticamente a cada imagen generada con la directiva NgOptimizedImage.
Incluimos una API simplificada para configurar la propiedad sizes
, que se usa para garantizar que cada imagen obtenga el tipo correcto de srcset
. Si no incluyes un atributo sizes
, sabremos que la imagen debe tener un tamaño fijo y debe obtener un srcset dependiente de la densidad, como el siguiente:
<img src="www.example.com/image.png" srcset="www.example.com/image.png?w=400 1x, www.example.com/image.png?w=800 2x" >
Este tipo de srcset garantiza que las imágenes se entreguen en un tamaño que tenga en cuenta la densidad de píxeles del dispositivo del usuario.
Por otro lado, si incluyes la propiedad sizes
, NgOptimizedImage
genera un srcset responsivo que incluye puntos de inflexión para muchos tamaños de dispositivos e imágenes comunes, con esta lista predeterminada de puntos de inflexión:
[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]
Generación de preconexión
Para mejorar el LCP, es importante reducir el tiempo que los usuarios dedican a descargar la imagen de LCP. En la sección anterior, viste cómo srcset
puede ayudar a transferir archivos de imagen más pequeños, pero una optimización igualmente importante es iniciar la transferencia lo antes posible. Una forma de hacerlo es usar etiquetas link rel="preconnect"
para iniciar la conexión con tu dominio de imagen.
Desde el principio, NgOptimizedImage te advirtió si no te conectabas previamente al dominio de tu imagen de LCP, pero la advertencia no es la solución ideal. Preferimos solucionar el problema por ti. Y eso es exactamente lo que hace NgOptimizedImage ahora, con la generación automática de preconexión.
Para admitir esta función, usamos el análisis de código estático para intentar detectar dominios de imágenes en los cargadores de NgOptimizedImage y generar automáticamente etiquetas de vínculo de conexión previa para esos dominios. Es posible que aún haya casos en los que se requieran vínculos de conexión previa manual, pero para la mayoría de los usuarios, la conexión previa automática significa un paso menos necesario para obtener un buen rendimiento de la imagen.
Compatibilidad mejorada con cargadores personalizados
Un elemento clave de NgOptimizedImage es la arquitectura del cargador, que permite que la directiva genere automáticamente URLs adaptadas a la CDN de imágenes de la aplicación. Se incluye un conjunto de cargadores integrados para CDN de uso general. También proporcionamos el uso de cargadores personalizados, que te permiten integrar NgOptimizedImage con casi cualquier solución de alojamiento de imágenes.
En el lanzamiento, estos cargadores personalizados tenían un alcance limitado y solo podían leer el atributo width
del elemento de imagen. En respuesta a los comentarios de los usuarios, agregamos compatibilidad con una estructura de datos loaderParams
personalizable, que permite pasar datos arbitrarios del elemento de imagen al cargador personalizado. Con la expansión, los cargadores personalizados pueden ser tan simples o complejos como lo requiera la infraestructura de imágenes de una aplicación.
En el siguiente ejemplo, se muestra cómo un cargador personalizado simple podría usar la API de loaderParams
para seleccionar entre dos dominios de imágenes alternativos:
const myCustomLoader = (config: ImageLoaderConfig) => {
if (config.loaderParams?.alternateDomain) {
return `https://alternate.domain.com/images/${config.src}`
}
return `https://primary.domain.com/images/${config.src}`;
};
En la documentación de Angular, puedes encontrar un ejemplo de un cargador personalizado más complejo.
Guía expandida para el rendimiento de las imágenes
Hasta ahora, todas las alertas de rendimiento de imágenes que agregamos a Angular formaban parte de la directiva NgOptimizedImage. Si no usas la directiva en la app, no recibirás ninguna guía sobre los problemas de rendimiento de las imágenes.
En Angular 17, expandimos el alcance de la guía de rendimiento de las imágenes para incluir todas las apps de Angular. Ahora, si detectamos patrones de imágenes que sabemos que son errores que afectan el rendimiento, como la carga diferida de tu imagen de LCP o la descarga de un archivo demasiado grande para la página, te lo informaremos, incluso si no usas NgOptimizedImage.
El rendimiento de las imágenes es importante para todas las apps, y nos complace seguir creando protecciones para ayudar a evitar errores comunes en las apps de Angular.
Mirando hacia el futuro
Ya estamos trabajando arduamente en el desarrollo del siguiente conjunto de funciones para NgOptimizedImage. Si bien el rendimiento de las imágenes sigue siendo nuestra preocupación central, también nos gustaría agregar funciones que mejoren la experiencia de los desarrolladores para asegurarnos de que NgOptimizedImage siga siendo una opción atractiva para incluir imágenes en aplicaciones de Angular.
Una función que es una prioridad para nosotros son los marcadores de posición de imagen. Por lo general, se usan para que la carga de imágenes se vea mejor en las aplicaciones web, pero pueden perjudicar el rendimiento si se implementan de forma incorrecta. Esperamos compilar un sistema de marcadores de posición de imagen que priorice el rendimiento en NgOptimizedImage. No te pierdas los anuncios en nuestro blog.