Contenido del curso

Nuevas Funcionalidades en Angular

Optimización de Rendimiento

Lazy loading de imágenes con ngSrc en Angular

Resumen

Optimizar imágenes en Angular es uno de los pasos más rentables para mejorar el rendimiento de tu sitio web. La directiva NgOptimizeImage y su atributo ngSrc te permiten reducir tiempos de carga, evitar saltos visuales molestos y aplicar lazy loading sin escribir lógica adicional. Esta guía te muestra cómo implementarla paso a paso en un store real.

¿Qué son los Web Vitals y por qué importan al optimizar imágenes?

Los Web Vitals son tres métricas que miden la experiencia real de un usuario en tu sitio: el loading (qué tan rápido carga la página), el INP (la interactividad) y el CLS o Cumulative Layout Shift (la estabilidad visual). Al usar ngSrc impactas directamente dos de estas métricas: el rendimiento de carga y el CLS [01:00].

El CLS es esa molestia que sientes cuando intentas hacer clic en un botón y, de repente, un banner se carga arriba y te empuja todo el contenido. Terminas dándole yes cuando querías no. Eso es justamente lo que la estabilidad visual busca evitar.

¿Qué hace la directiva NgOptimizeImage en Angular? Reemplaza el src tradicional de la etiqueta <img> por ngSrc, aplicando optimizaciones automáticas de carga y reservando espacio para evitar saltos visuales mientras la imagen se descarga.

¿Cómo implementar ngSrc en un componente Angular?

El primer paso es importar la directiva desde @angular/common. Una vez importada, basta con cambiar src por ngSrc en tu etiqueta <img>. En el ejemplo, se aplica tanto en el componente products-detail como en el carrusel de imágenes [03:30].

html <img ngSrc="ruta/imagen.jpg" width="80" height="80" />

Al hacerlo notarás que las imágenes dejan de cargar si no cumples las restricciones que la directiva exige. Y aquí viene lo interesante: esas restricciones son las que garantizan la optimización.

¿Por qué necesito definir width y height?

Para mantener estabilidad visual, Angular necesita conocer las dimensiones del espacio que la imagen ocupará. Así reserva el cuadro y lo rellena cuando la imagen termine de descargarse, sin mover el resto del layout.

En el carrusel del store funcionó bien con width="80" y height="80". El problema aparece con imágenes responsive, como un cover, donde no puedes fijar dimensiones absolutas porque cambian entre mobile y desktop.

¿Cómo usar fill para imágenes responsive?

Cuando no puedes definir un ancho y alto fijos, la solución es el atributo fill. Le dices a Angular que la imagen debe rellenar a su contenedor padre más cercano que tenga la propiedad CSS position: relative [07:45].

html

<div class="relative h-80"> <img ngSrc="cover.jpg" fill /> </div>

Si solo activas fill sin un padre relativo, la imagen se irá hasta el body y ocupará toda la pantalla. Por eso necesitas tres elementos trabajando juntos:

  • Un contenedor padre con position: relative (o la clase relative en Tailwind).
  • Un alto fijo en ese contenedor, por ejemplo h-80 o h-96.
  • El atributo fill en la etiqueta <img> con ngSrc.

¿Por qué fill busca un padre relative? Porque internamente la imagen se posiciona de forma absoluta dentro de ese contenedor. Sin un ancestro relative, se escapa hasta el body. Por eso siempre debes envolverla en un div con esa propiedad.

El ancho lo hereda dinámicamente del padre, lo que te da responsive sin esfuerzo. Solo necesitas controlar la altura para evitar que la imagen se estire o pierda su aspect ratio.

¿Cómo activar lazy loading para mejorar el performance?

El lazy loading es la carga dinámica de imágenes a medida que el usuario hace scroll. ¿Para qué pedir una imagen del final de la página si quizás el usuario nunca llega ahí? Cada request evitado es rendimiento ganado.

Con NgOptimizeImage solo agregas un atributo:

html <img ngSrc="producto.jpg" fill loading="lazy" />

En el panel Network del navegador puedes verificar el efecto: al recargar la página, solo se descargan las imágenes visibles. A medida que haces scroll, Angular detecta la proximidad (aproximadamente 10 píxeles antes de entrar en pantalla) y dispara el request justo a tiempo [14:20].

¿Cuándo conviene combinar fill, dimensiones fijas y lazy?

La estrategia depende del tipo de imagen:

  1. Imágenes de tamaño conocido (avatares, miniaturas, íconos): usa width y height fijos.
  2. Imágenes responsive (covers, banners, hero images): usa fill con un padre relative y altura definida.
  3. Imágenes fuera del viewport inicial (productos del feed, galerías largas): añade loading="lazy" para diferir su carga.

Un detalle práctico: al probar lazy loading, limpia el caché del navegador. Si las imágenes ya están cacheadas no verás el efecto y podrías pensar que la directiva no funciona.

¿Qué ganas al usar NgOptimizeImage en tu aplicación?

Obtienes dos mejoras concretas en tus Web Vitals: reduces el Cumulative Layout Shift porque cada imagen reserva su espacio antes de cargar, y mejoras el performance porque evitas requests innecesarios mediante lazy loading. Todo esto sin escribir lógica personalizada, solo configurando atributos.

En el store del ejemplo, el carrusel quedó estable, el cover responsive dejó de saltar y el listado de productos en el home ahora carga progresivamente según el scroll. ¿Ya probaste medir el antes y después en Lighthouse? Cuéntame en los comentarios qué métricas mejoraste tras aplicar ngSrc en tu proyecto.