Command Palette

Search for a command to run...

Lazy Loading en JavaScript: Carga Recursos Bajo Demanda

Aprende a implementar lazy loading para cargar recursos y ejecutar código solo cuando es necesario, mejorando drásticamente el tiempo de carga inicial de tus aplicaciones.

Lectura: 14 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • Lazy loading carga recursos solo cuando son necesarios, no al inicio
  • Reduce drásticamente el tiempo de carga inicial y el uso de memoria
  • Implementa lazy loading de imágenes con Intersection Observer API
  • Usa dynamic import para lazy loading de componentes y módulos
  • Considera el SEO y la experiencia del usuario al implementar lazy loading

Introducción

En el desarrollo web moderno, las aplicaciones suelen cargar muchos recursos al inicio: imágenes, scripts, estilos y componentes. Esto puede resultar en tiempos de carga lentos, especialmente en dispositivos móviles con conexiones limitadas. El lazy loading es una técnica que carga estos recursos solo cuando son necesarios, mejorando drásticamente el rendimiento y la experiencia del usuario.

El concepto es simple: en lugar de cargar todo al inicio, carga solo lo que el usuario necesita en ese momento. Cuando el usuario navega o interactúa con la aplicación, los recursos adicionales se cargan bajo demanda. Esto reduce el tiempo de carga inicial, el consumo de ancho de banda y el uso de memoria, haciendo que la aplicación se sienta más rápida y responsiva.

Impacto en Métricas Web

El lazy loading mejora significativamente las métricas Core Web Vitals de Google. Reduce el LCP (Largest Contentful Paint) al no cargar imágenes grandes al inicio, mejora el FID (First Input Delay) al ejecutar menos JavaScript inicialmente, y optimiza el CLS (Cumulative Layout Shift) al reservar espacio para contenido que se cargará después.

¿Qué es Lazy Loading?

Lazy loading es una técnica de optimización que pospone la carga de recursos hasta que son necesarios. En lugar de cargar todos los recursos al inicio de la aplicación, solo se cargan aquellos que el usuario necesita inmediatamente. Los recursos adicionales se cargan bajo demanda a medida que el usuario interactúa con la aplicación.

Esta técnica es especialmente útil para aplicaciones con mucho contenido: sitios de e-commerce con muchos productos, blogs con muchas imágenes, aplicaciones con múltiples rutas o componentes, y cualquier aplicación que cargue recursos pesados como imágenes, videos o módulos de JavaScript. Al aplicar lazy loading, puedes reducir el tiempo de carga inicial en un 50-80% en muchos casos.

  • Imágenes fuera del viewport (viewport inicial)
  • Componentes y rutas que no son visibles inicialmente
  • Módulos de JavaScript que no son necesarios al inicio
  • Videos y contenido multimedia pesado
  • Datos de APIs que no son necesarios inmediatamente

Lazy Loading de Imágenes

Las imágenes suelen ser el recurso más pesado en una aplicación web. Implementar lazy loading de imágenes puede reducir drásticamente el tiempo de carga inicial, especialmente en páginas con muchas imágenes como galerías, blogs o sitios de e-commerce. La Intersection Observer API es la forma moderna y eficiente de implementar esto.

Intersection Observer API

La Intersection Observer API es una API moderna del navegador que permite detectar cuando un elemento entra o sale del viewport. Es más eficiente que escuchar eventos de scroll porque el navegador optimiza las notificaciones y solo te avisa cuando realmente necesitas saber que un elemento es visible.

intersection-observer.js
Loading code...

Esta implementación crea un observer que detecta cuando las imágenes entran en el viewport. Cuando una imagen es visible, carga su src real y deja de observarla. El atributo data-src contiene la URL real de la imagen, mientras que src contiene un placeholder ligero o está vacío. Esto evita cargar imágenes que el usuario nunca verá.

Placeholder y Loading State

Para mejorar la experiencia del usuario, usa un placeholder ligero mientras la imagen se carga. Puede ser una imagen gris pequeña, un SVG simple, o incluso un color de fondo. También considera añadir un estado de loading con un spinner o skeleton screen para indicar que el contenido se está cargando.

Atributo Loading Nativo

Los navegadores modernos soportan el atributo loading="lazy" en elementos img e iframe. Esta es la forma más simple de implementar lazy loading de imágenes, ya que el navegador maneja todo automáticamente. Solo necesitas añadir el atributo y el navegador se encarga del resto.

loading-attribute.js
Loading code...

El atributo loading="lazy" es soportado por Chrome, Firefox, Edge y Safari. Es la forma más simple de implementar lazy loading, pero tiene menos control que Intersection Observer. No puedes personalizar el umbral de visibilidad, añadir animaciones de carga o manejar errores de carga de forma específica.

Lazy Loading con Imágenes Responsivas

Cuando combinas lazy loading con imágenes responsivas usando srcset y sizes, puedes optimizar aún más el rendimiento. La imagen correcta se carga según el tamaño del viewport y la densidad de píxeles del dispositivo, pero solo cuando la imagen es visible para el usuario.

lazy-loading-responsive.js
Loading code...

Esta implementación combina lazy loading con imágenes responsivas. El atributo srcset define diferentes versiones de la imagen para diferentes tamaños de pantalla, y sizes indica qué versión usar según el tamaño del viewport. La imagen solo se carga cuando es visible, y se carga la versión óptima para el dispositivo del usuario.

CLS y Layout Shift

Para evitar CLS (Cumulative Layout Shift), reserva espacio para las imágenes que se cargarán con lazy loading. Usa los atributos width y height en las imágenes o reserva espacio con CSS. Esto evita que el contenido salte cuando las imágenes se cargan, mejorando la experiencia del usuario y las métricas Core Web Vitals.

Lazy Loading de Componentes

Además de las imágenes, también puedes aplicar lazy loading a componentes y módulos de JavaScript. Esto es especialmente útil en aplicaciones con múltiples rutas o componentes pesados que no son necesarios al inicio. El dynamic import de JavaScript permite cargar módulos bajo demanda, reduciendo el tamaño del bundle inicial.

Dynamic Import

El dynamic import es una característica de JavaScript que permite importar módulos dinámicamente en tiempo de ejecución. A diferencia del import estático que carga todos los módulos al inicio, el dynamic import carga el módulo solo cuando se ejecuta la función import(). Esto es ideal para lazy loading de componentes.

dynamic-import.js
Loading code...

Esta implementación muestra cómo usar dynamic import para cargar un componente bajo demanda. El componente no se carga hasta que se ejecuta loadComponent(), lo que reduce el tamaño del bundle inicial. El dynamic import devuelve una Promise, por lo que puedes manejar el estado de carga y mostrar un spinner o skeleton mientras el componente se carga.

Lazy Loading de Rutas

En aplicaciones con múltiples rutas, el lazy loading de rutas es una de las optimizaciones más efectivas. En lugar de cargar todas las rutas al inicio, cada ruta se carga solo cuando el usuario navega a ella. Esto reduce drásticamente el tiempo de carga inicial y el tamaño del bundle.

lazy-loading-rutas.js
Loading code...

Esta implementación muestra cómo configurar lazy loading de rutas en una aplicación JavaScript vanilla. Cada ruta se define como una función que usa dynamic import para cargar el componente correspondiente. Cuando el usuario navega a una ruta, solo el componente de esa ruta se carga, no todos los componentes de todas las rutas.

Code Splitting

El lazy loading de rutas es una forma de code splitting, que divide tu código en múltiples archivos más pequeños que se cargan bajo demanda. Herramientas como Webpack, Rollup y Vite soportan code splitting automáticamente cuando usas dynamic import. Esto reduce el tamaño del bundle inicial y mejora el tiempo de carga.

Consideraciones y Mejores Prácticas

Aunque el lazy loading es una técnica poderosa de optimización, hay consideraciones importantes que debes tener en cuenta para implementarla correctamente y evitar problemas de SEO, accesibilidad o experiencia del usuario.

SEO y Lazy Loading

El lazy loading puede afectar negativamente el SEO si no se implementa correctamente. Los crawlers de los motores de búsqueda pueden no ejecutar JavaScript o no esperar a que el contenido se cargue con lazy loading, lo que puede resultar en que el contenido no se indexe correctamente.

seo-y-lazy-loading.js
Loading code...

Esta implementación muestra cómo manejar el SEO con lazy loading. El contenido crítico para SEO debe estar en el HTML inicial, no cargarse con lazy loading. Solo aplica lazy loading a contenido secundario como imágenes adicionales, comentarios o componentes que no son críticos para el SEO. Usa noscript para proporcionar contenido alternativo para crawlers que no ejecutan JavaScript.

Crawlers y JavaScript

Los crawlers de Google ejecutan JavaScript y pueden indexar contenido cargado con lazy loading, pero otros crawlers como Bing pueden no hacerlo. Para asegurar que tu contenido sea indexado correctamente, proporciona el contenido crítico en el HTML inicial y usa lazy loading solo para contenido secundario.

Accesibilidad

El lazy loading puede afectar la accesibilidad si no se implementa correctamente. Los usuarios con lectores de pantalla o conexiones lentas pueden tener problemas si el contenido no carga correctamente o si no hay indicadores visibles de que el contenido se está cargando.

accesibilidad-lazy-loading.js
Loading code...

Esta implementación muestra cómo hacer el lazy loading accesible. Usa atributos ARIA para indicar el estado de carga, proporciona texto alternativo para las imágenes, y maneja errores de carga de forma accesible. Los usuarios con lectores de pantalla sabrán cuando el contenido se está cargando y si hay errores.

Fallback y Error Handling

Es importante manejar errores de carga y proporcionar fallbacks apropiados. Si una imagen o componente falla al cargar, debes mostrar un contenido alternativo o un mensaje de error en lugar de dejar el espacio en blanco o roto.

fallback-error-handling.js
Loading code...

Esta implementación muestra cómo manejar errores de carga y proporcionar fallbacks. Si una imagen falla al cargar, se muestra una imagen de fallback o un icono. Si un componente falla al cargar, se muestra un mensaje de error y un botón para reintentar. Esto mejora la experiencia del usuario y evita que la aplicación se vea rota.

Progressive Enhancement

Aplica progressive enhancement: proporciona una versión básica funcional sin JavaScript, y mejora la experiencia con JavaScript cuando está disponible. Esto asegura que tu aplicación funcione incluso si JavaScript falla o si el usuario lo tiene deshabilitado, mientras aprovechas las capacidades modernas cuando están disponibles.

Resumen: Lazy Loading en JavaScript

Conceptos principales:

  • Lazy loading carga recursos solo cuando son necesarios
  • Reduce el tiempo de carga inicial y el uso de memoria
  • Intersection Observer API es la forma moderna de implementarlo
  • Dynamic import permite lazy loading de módulos JavaScript
  • Atributo loading='lazy' es soportado por navegadores modernos

Mejores prácticas:

  • Usa Intersection Observer para lazy loading de imágenes
  • Reserva espacio para evitar CLS (Cumulative Layout Shift)
  • Aplica lazy loading solo a contenido secundario, no crítico para SEO
  • Proporciona fallbacks y maneja errores de carga
  • Considera la accesibilidad al implementar lazy loading