Carga asíncrona: async vs defer y rendimiento

La carga asíncrona obtiene recursos sin bloquear la página. Cómo funcionan los scripts async y defer, import() y las imágenes lazy, y los errores típicos.

¿Qué es la carga asíncrona?

La carga asíncrona consiste en obtener un recurso sin impedir que el navegador haga otras tareas, como analizar el HTML o renderizar. En la web incluye los scripts async y defer, el import() dinámico, las imágenes con carga diferida y las peticiones fetch. La página sigue respondiendo mientras llega el recurso y lo usa cuando está listo.

async vs defer

Un script clásico sin ninguno de los dos atributos se descarga y ejecuta de inmediato, y el navegador detiene el análisis de la página mientras tanto. async y defer descargan el script en paralelo al análisis. Se diferencian en cuándo se ejecuta.

  • async: se ejecuta en cuanto termina de descargarse, lo que puede pausar el análisis, y no garantiza el orden entre scripts.
  • defer: se ejecuta cuando el documento ya está analizado, antes de DOMContentLoaded, y en el orden en que aparecen los scripts en la página.
  • type="module": se difiere por defecto, así que defer no tiene efecto.

Ambos atributos solo funcionan en scripts con src; en scripts en línea no hacen nada. Si se ponen los dos, prevalece async. Fuente: MDN, el elemento script.

Ejemplo

<!-- classic script, blocks parsing -->
<script src="app.js"></script>

<!-- downloads in parallel, runs when ready, any order -->
<script async src="analytics.js"></script>

<!-- downloads in parallel, runs after parsing, in order -->
<script defer src="app.js"></script>

<!-- module scripts are deferred by default -->
<script type="module" src="main.js"></script>

Un reparto habitual: defer para el código de tu app, que depende del DOM y de otros scripts, y async para scripts de terceros independientes, como la analítica.

Otras formas de carga asíncrona

  • Importación dinámica: import() carga un módulo ES bajo demanda y devuelve una promesa. Es la base de la división de código, donde un fragmento se carga solo cuando hace falta.
  • Imágenes e iframes diferidos: loading="lazy" pospone los recursos fuera de pantalla hasta que el usuario se acerca al hacer scroll. Consulta la carga diferida (lazy loading).
  • Peticiones de datos: llamadas fetch y XHR que rellenan la página después del primer renderizado.

Errores comunes

  • async en scripts que dependen entre sí. El orden no está garantizado, así que un plugin puede ejecutarse antes que su biblioteca.
  • Diferir la imagen principal. El elemento más grande visible suele ser el que mide el Largest Contentful Paint, así que diferirlo retrasa la métrica. Difiere solo lo que empieza fuera de pantalla.
  • Scripts bloqueantes en el head. Retienen la ruta crítica de renderizado. Difiérelos salvo que el primer pintado los necesite.
  • Contenido que aparece tarde y mueve el diseño. Reserva espacio para el contenido cargado de forma asíncrona.
  • Sin gestión de errores. Un import() o fetch fallido rechaza su promesa; trátalo o la función nunca aparecerá sin avisar.

Carga asíncrona, testing y monitorización

La carga asíncrona mejora lo que el usuario ve primero, pero traslada el trabajo en lugar de eliminarlo. Los scripts siguen descargándose y ejecutándose, así que mide el resultado en el navegador con tiempos de DOM listo y Core Web Vitals, no solo con tiempos de respuesta del servidor. Nuestra guía de rendimiento de JavaScript muestra cómo async, defer y la división de código afectan al hilo principal, y la monitorización de velocidad de página sigue el efecto de cada cambio de forma programada.

Preguntas frecuentes sobre la carga asíncrona

¿Cuál es la diferencia entre async y defer?

Ambos descargan el script sin bloquear el analizador. async lo ejecuta en cuanto llega, sin orden garantizado. defer lo ejecuta tras el análisis, antes de DOMContentLoaded, en el orden del documento.

¿Cuál debo usar?

Usa defer para scripts que necesitan el DOM o dependen unos de otros. Usa async para scripts independientes, como la analítica, que pueden ejecutarse cuando lleguen.

¿async y defer funcionan en scripts en línea?

No. Sin atributo src no tienen efecto. Los scripts de módulo se difieren por defecto.

¿La carga asíncrona hace más rápida una página?

Normalmente mejora lo pronto que se renderiza y se puede usar, porque no se detiene el analizador. El trabajo total es el mismo, así que comprueba el efecto con mediciones reales.

¿La carga diferida es lo mismo que la carga asíncrona?

La carga diferida es un tipo de ella: el recurso se obtiene solo cuando hace falta, por ejemplo cuando una imagen se acerca a la pantalla. Los scripts async se obtienen enseguida, solo que sin bloquear la página.

¿Qué tan rápido es tu sitio web?

Mejora su velocidad y SEO sin problemas con nuestra Prueba de Velocidad gratuita.

Prueba de velocidad de sitio web gratis

Analice la velocidad de carga de su sitio web y mejore su rendimiento con nuestro comprobador de velocidad de página gratuito.