JavaScript Defer vs Async y cómo afecta a los Core Web Vitals

Aprende cuándo usar async en JavaScript y cuándo usar defer para obtener los mejores resultados de Core Web Vitals

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-02

JavaScript Defer vs Async y cómo afecta a los Core Web Vitals

Siempre que audito los Core Web Vitals de un cliente, a menudo descubro que hay poca distinción en una página entre JavaScript que bloquea el analizador (sync), asíncrono o diferido (deferred). Eso es una pena porque diferentes scripts tienen diferentes tiempos óptimos.

Última revisión por Arjen Karel en marzo de 2026

De acuerdo con el Web Almanac de 2025, solo el 15% de las páginas móviles superan la auditoría de recursos que bloquean el renderizado (render-blocking resources). La página mediana carga 22 scripts que suman más de 630 KB, con 251 KB de ese JavaScript quedando completamente sin usar. La mayoría de los sitios están cargando demasiado JavaScript, y cargándolo en el momento equivocado.

En resumen

El JavaScript 'Normal' en el head de la página bloquea el navegador para que no analice el HTML hasta que se descargue y ejecute. Los scripts Async se descargan en segundo plano pero se ejecutan tan pronto como están listos, lo que aún puede interrumpir el análisis (parsing). Los scripts diferidos (deferred) se descargan en segundo plano y esperan hasta que el análisis esté completo antes de ejecutarse, en el orden del documento.

Usa defer para cualquier cosa que toque el DOM. Usa async para scripts que son completamente independientes (analytics, píxeles de seguimiento). No uses ninguno de los dos (sync) solo si el script debe ejecutarse antes de que la página se renderice. En caso de duda, usa defer.

1. JavaScript síncrono (sync)

De forma predeterminada, los scripts en el head de la página son síncronos. Cuando el navegador encuentra un script síncrono deja de analizar el HTML, descarga el script y lo ejecuta antes de continuar. Esto significa que no se pintan píxeles hasta que todos los scripts sync terminan. Para scripts grandes o lentos, esto crea un retraso visible en el First Contentful Paint.

<!DOCTYPE html>
<html>
<head>
  <title>Ejemplo de JavaScript Sync</title>
  <script src="script1.js"></script>
  <script src="script2.js"></script>
</head>
<body>
  <!-- Contenido de la página aquí -->
</body>
</html>

El navegador debe descargar y ejecutar script1.js antes incluso de comenzar con script2.js. Mientras tanto, no se renderiza nada. La página móvil mediana ya tiene un Total Blocking Time de casi 2 segundos en 2025. Los scripts síncronos en el head empeoran esto.

2. JavaScript asíncrono (async)

Agregar el atributo async le dice al navegador que descargue el script en segundo plano mientras continúa analizando el HTML. El script se ejecuta tan pronto como termina de descargarse, sin importar dónde se encuentre el analizador (parser) en ese momento. El análisis solo se detiene durante la ejecución.

<!DOCTYPE html>
<html>
<head>
  <title>Ejemplo de JavaScript Async</title>
  <script src="script1.js" async></script>
  <script src="script2.js" async></script>
</head>
<body>
  <!-- Contenido de la página aquí -->
</body>
</html>

Los scripts Async no garantizan el orden de ejecución. El script que termine de descargarse primero se ejecuta primero. Si script2.js depende de script1.js, async romperá las cosas de forma impredecible. Usa async solo para scripts que son completamente independientes entre sí y del DOM.

Una cosa a tener en cuenta: en Chrome, los scripts async obtienen una prioridad de red baja (Low network priority) de forma predeterminada. Esto significa que el navegador puede comenzar a descargarlos más tarde de lo que esperas. Si necesitas que un script async se cargue rápidamente (sin bloquear el análisis), agrega fetchpriority="high".

3. JavaScript diferido (defer)

El atributo defer también descarga el script en segundo plano, pero la ejecución se pospone hasta que el documento HTML esté completamente analizado. Los scripts diferidos se ejecutan en el orden del documento, justo antes de que se dispare el evento DOMContentLoaded.

<!DOCTYPE html>
<html>
<head>
  <title>Ejemplo de JavaScript Defer</title>
  <script src="script1.js" defer></script>
  <script src="script2.js" defer></script>
</head>
<body>
  <!-- Contenido de la página aquí -->
</body>
</html>

Defer es la opción más segura para la mayoría de los scripts. El DOM está completamente disponible cuando se ejecuta el script, se conserva el orden de ejecución y no se bloquea el primer pintado (first paint). The Telegraph difirió todos sus scripts y mejoró el tiempo de carga de los anuncios en 4 segundos.

4. Scripts de módulos (Module scripts)

Si usas módulos ES (<script type="module">), obtienes el comportamiento defer automáticamente. Los scripts de módulos se descargan en segundo plano, se ejecutan después del análisis y mantienen el orden. Agregar defer explícitamente no tiene efecto porque ya es el valor predeterminado.

Puedes agregar async a un script de módulo si deseas que se ejecute tan pronto como se resuelva su gráfico de dependencias, en lugar de esperar a que se complete el análisis.

Tabla de comparación

Atributo Descargas Se ejecuta ¿Bloquea el análisis? ¿Orden conservado?
ninguno (sync) Bloquea el análisis durante la descarga Inmediatamente después de la descarga Sí (descarga + ejecución)
async En segundo plano Tan pronto como se completa la descarga Solo durante la ejecución No
defer En segundo plano Después del análisis HTML, antes de DOMContentLoaded No
type="module" En segundo plano Después del análisis HTML (igual que defer) No

Preguntas comunes

¿Qué pasa si uso tanto async como defer en la misma etiqueta? Async gana. El atributo defer se ignora por completo. Este patrón solía existir como una solución alternativa (fallback) para IE9, pero en 2026 no hay razón para usar ambos.

¿Funcionan async y defer en scripts en línea (inline scripts)? No. Ambos atributos se ignoran en los scripts en línea clásicos (sin src). Solo funcionan en scripts externos. La excepción es <script type="module">, que es diferido por defecto incluso cuando está en línea.

¿Es mejor defer que poner scripts al final del body? Sí. Un script diferido en el <head> comienza a descargarse inmediatamente (en paralelo con el análisis HTML). Un script al final del body no puede comenzar a descargarse hasta que el analizador lo alcance. Defer te brinda un descubrimiento más temprano y una ejecución más tardía, que es lo mejor de ambos mundos.

Cómo async y defer afectan los Core Web Vitals

Los scripts síncronos perjudican directamente al FCP porque no se pinta nada hasta que terminan. También perjudican al LCP si el elemento LCP no puede renderizarse hasta que los scripts se completen.

Los scripts async mejoran el FCP (el primer pintado no está bloqueado por la descarga) pero aún pueden causar problemas de INP si se ejecutan durante la interacción del usuario y bloquean el hilo principal (main thread).

Los scripts defer te brindan las mejores métricas de pintado (paint metrics) porque no interfieren en absoluto con el renderizado inicial. La compensación: si tu página depende de JavaScript para mostrar contenido (single-page apps), defer puede retrasar el LCP porque el contenido no aparece hasta que el script se ejecuta después del análisis.

En los datos de monitoreo de CoreDash, los sitios que movieron todos los scripts no críticos de sync a defer vieron mejorar su FCP en [CD:placeholder] ms en promedio.

Yendo un paso más allá: carga scripts bajo demanda

Async y defer pueden acelerar una página al no bloquear el analizador, pero es importante tener en cuenta que diferir scripts no resolverá todos tus problemas. Por ejemplo, el elemento Largest Contentful Paint es vulnerable a la competencia de red y CPU causada por scripts diferidos y async. La Interaction to Next Paint también se ve afectada por los scripts que se ejecutan temprano durante la carga de la página. Es por eso que, siempre que sea posible, debes cargar los scripts bajo demanda para tener más control sobre su impacto en el rendimiento de la página. Lee cómo cargamos los scripts bajo demanda.

Para obtener una descripción completa de todas las estrategias de carga de JavaScript, consulta 16 métodos para diferir JavaScript. Si estás lidiando con la advertencia de recursos que bloquean el renderizado de Lighthouse, esa guía cubre la solución. También puedes afinar la carga con niveles de prioridad de JavaScript y elegir la ubicación óptima del script en el head vs footer.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

Ask AI why your INP spiked.

CoreDash is the only RUM tool with MCP support. Connect it to your AI agent and query your Core Web Vitals data in natural language. No more clicking through dashboards.

See How It Works
JavaScript Defer vs Async y cómo afecta a los Core Web VitalsCore Web Vitals JavaScript Defer vs Async y cómo afecta a los Core Web Vitals