Los atributos async y defer controlan cómo el navegador descarga y ejecuta scripts externos sin bloquear el parsing del HTML. Async ejecuta el script en cuanto termina la descarga; defer espera a que el HTML esté completamente parseado y respeta el orden de declaración. Elegir mal entre los dos puede romper dependencias entre librerías y arruinar el rendimiento de tu web.
Qué hacen async y defer y por qué importan al cargar librerías
Sin async ni defer, el navegador detiene el parsing del HTML cada vez que encuentra un <script>, lo descarga, lo ejecuta y recién ahí continúa. Con async, el script se descarga en paralelo y se ejecuta en cuanto está listo, sin esperar al HTML. Con defer, también se descarga en paralelo pero la ejecución espera a que el HTML esté completamente parseado — y respeta el orden de los scripts.
| Modo | Descarga | Ejecución | Bloquea HTML |
|---|---|---|---|
| Normal (sin atributo) | Secuencial | Inmediata | Sí |
async | Paralela | En cuanto termina | Momentáneamente |
defer | Paralela | Al final del parsing | No |

Async vs defer — diferencias que cambian todo cuando hay dependencias
La diferencia técnica es simple: async no garantiza orden de ejecución y defer sí. El problema real aparece cuando tienes múltiples librerías que dependen entre sí. Con async, la librería que termina de descargarse primero se ejecuta primero, sin importar cómo la hayas declarado en el HTML. Con defer, el orden se respeta siempre. Ese detalle cambia absolutamente todo en proyectos con dependencias entre librerías.
Cuándo async rompe tu código y cuándo es la mejor opción
He intentado cargar librerías fundamentales para el renderizado con async y el resultado fue romper el sitio — los componentes cargaban después del HTML y ya no mostraban datos correctamente. El síntoma es confuso al principio: la página carga, pero partes de la interfaz aparecen vacías o con errores en consola que señalan variables indefinidas.
Async tiene sentido cuando el script es completamente independiente. Lo uso principalmente con librerías de analítica o píxeles como GTM o Meta Pixel: necesito que empiecen a capturar datos de usuario cuanto antes, pero si cargan un segundo después del HTML, no pasa absolutamente nada. Para esos casos, async es perfecto.
Resumen de cuándo usar async:
- Scripts de analítica (Google Tag Manager, Meta Pixel)
- Chat widgets completamente independientes del DOM
- Píxeles de tracking que no dependen de otras librerías
- Scripts de A/B testing que se autoinician
Por qué defer es la opción segura para la mayoría de librerías
Defer lo reservo para componentes que añaden animaciones o interactividad — cosas que se activan al cargar el HTML pero que no son críticas para que el sitio funcione. Al deferir esas librerías, el usuario ve el contenido primero y la capa interactiva llega después, sin que note la diferencia.
Lo que no toco con defer ni async son los scripts nativos de plataformas como Shopify, WordPress o Webflow, y tampoco los bundles principales de frameworks. Son vitales para el funcionamiento del sitio y, por lo regular, ya están bien optimizados por sus propios equipos. Meterles mano sin entender bien sus dependencias internas es buscar problemas.
Resumen de cuándo usar defer:
- Librerías de animaciones (GSAP, AOS, ScrollReveal)
- Componentes de UI que no bloquean el contenido principal
- Scripts con dependencias entre sí que deben ejecutarse en orden
- Librerías que necesitan el DOM completo para inicializarse

Guía práctica — async y defer aplicado a librerías reales
Aplicar async y defer correctamente requiere conocer el rol de cada librería en tu proyecto. No existe una regla universal: depende de si el script necesita el DOM, si otras librerías dependen de él y qué tan crítico es para el renderizado inicial. A continuación, los criterios que Andres aplica en proyectos reales con librerías específicas.
Frameworks como React o Vue — qué atributo usar y por qué
Mi experiencia concreta es con React y Vue. He probado async en ambos y el resultado fue inconsistente: en algunos casos los scripts se ejecutan en un orden incorrecto y dañan funcionalidades que antes andaban bien. En pocos casos funcionó, pero no es un resultado confiable.
Mi recomendación: si estás trabajando con estos frameworks, la prioridad es optimizar los bundles desde adentro — code splitting, lazy loading, tree shaking — antes de tocar cómo se cargan. Agregar async o defer a un bundle de React es un parche sobre un problema que tiene mejor solución aguas arriba.
<!-- No recomendado para el bundle principal de React -->
<script async src="main.bundle.js"></script>
<!-- Defer puede funcionar si el bundle es autocontenido -->
<script defer src="main.bundle.js"></script>Antes de tocar los atributos de carga en un framework, considera estas optimizaciones internas:
- Implementar code splitting para dividir el bundle principal
- Aplicar lazy loading a rutas y componentes no críticos
- Usar tree shaking para eliminar código no utilizado
- Evaluar si realmente necesitas el framework completo o una versión más ligera
Librerías de utilidad y scripts de terceros — el caso perfecto para async
Para jQuery, Lodash o Moment.js he usado async con buenos resultados — mejoran notablemente el tiempo de renderizado sin afectar la funcionalidad, siempre que no haya otra librería en la página que dependa de ellas. Si jQuery es la base de otros plugins, cambia la ecuación.
Con Google Analytics, chat widgets y píxeles de tracking, casi siempre uso async. La lógica es la misma: necesitan empezar a ejecutarse pronto para no perder datos, pero no bloquear el HTML por eso. El único caso donde he usado defer para un widget fue con componentes secundarios que no son críticos para la analítica ni para la interacción del usuario — y los resultados también fueron buenos.
<!-- Scripts de terceros independientes: async -->
<script async src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXX"></script>
<script async src="meta-pixel.js"></script>
<!-- Librerías con dependencias o animaciones: defer -->
<script defer src="animations-library.js"></script>
<script defer src="ui-components.js"></script>
Errores comunes y cómo los he resuelto en proyectos reales
El error más básico que cometía antes era simplemente no usar ninguno de los dos atributos, y compensar tratando de no incluir librerías pesadas. Eso funciona hasta cierto punto — cuando el proyecto crece y necesitas varias librerías en páginas principales, el bloqueo del DOM se vuelve un problema real y medible.
Tuve un caso con la página web de una empresa que cargaba librerías de analítica junto con componentes de animaciones. El TBT estaba en un par de minutos — sí, minutos. Empezamos a analizar qué bloqueaba el renderizado con el inspector del navegador y PageSpeed Insights, y nos dimos cuenta de que la mayoría de esas cargas podían diferirse sin ningún impacto funcional. Aplicamos una combinación de async para los scripts de analítica y defer para las animaciones, y pasamos de minutos de carga a menos de 8 segundos.
Los errores más frecuentes que Andres ha identificado en proyectos reales:
- No usar ningún atributo y acumular bloqueos de DOM en páginas con múltiples librerías
- Aplicar async a librerías que son base de otros plugins (jQuery con plugins dependientes)
- Usar defer en scripts que construyen partes del HTML durante el parsing
- Combinar async y defer en el mismo script sin entender cuál tiene prioridad
El error de dependencias que nadie te explica
El caso más concreto que tuve fue al intentar activar defer en una librería que parecía no crítica, pero que en realidad era fundamental para construir partes del HTML. El síntoma: secciones enteras de la página dejaban de renderizarse. No había un error gritando en consola desde el inicio — simplemente el contenido no aparecía.
La solución fue revertir el cambio en esa librería específica y dejarla cargando de forma normal. Aprendí algo que parece obvio pero no lo es cuando estás optimizando en caliente: antes de aplicar defer o async a cualquier script, identifica si algo en el HTML depende de que esa librería ya esté disponible. Si la respuesta es sí, no la toques.
El inspector del navegador y PageSpeed Insights normalmente dejan el panorama claro. No es un problema difícil de diagnosticar si sabes dónde mirar. Si quieres profundizar en cómo medir el impacto real en tus métricas Core Web Vitals, revisa también cómo interpretar los datos de Core Web Vitals en tu proyecto y cómo complementar estas optimizaciones con una estrategia completa de rendimiento web. Para entender mejor el contexto de carga de recursos, también es útil conocer cómo funciona el navegador al procesar HTML y JavaScript.
FAQ — Preguntas frecuentes sobre async y defer en librerías
¿Puedo usar async y defer en el mismo script?
No. Son atributos mutuamente excluyentes en la misma etiqueta <script>. Si pones ambos, los navegadores modernos priorizan async. Elige uno según si necesitas respetar el orden de ejecución (defer) o no (async). Combinarlos no produce ningún beneficio adicional.
¿Async y defer afectan los scripts inline?
No. Estos atributos solo funcionan con scripts externos que tienen el atributo src. Un script con código inline directamente en el HTML no puede usar async ni defer — siempre se ejecuta en el punto donde está declarado, bloqueando el parsing en ese momento.
¿Defer siempre es mejor que nada para librerías con dependencias?
No siempre. Si una librería es necesaria para que el HTML se construya correctamente, defer va a romper esa dependencia porque la ejecución se pospone hasta que el parsing termine. En esos casos, la carga normal o reorganizar el orden de los scripts es la solución correcta.
¿Cómo sé qué scripts están bloqueando el renderizado?
Abre PageSpeed Insights o el panel de Performance del inspector del navegador. Ambos muestran exactamente qué recursos bloquean el rendering y cuánto tiempo consumen. Es el primer paso antes de tocar cualquier atributo en tus scripts de producción.
Revisa ahora los scripts de tu proyecto y aplica defer a toda librería con dependencias — el impacto en rendimiento es inmediato y medible. Si no sabes por dónde empezar, PageSpeed Insights te da el mapa en segundos.