Carga Asíncrona: Definición, async vs defer, Performance
La carga async permite descargar recursos sin bloquear la página — scripts async/defer, imágenes lazy, dynamic imports. Crítico para LCP rápido + TBT bajo.
¿Qué es carga asíncrona?
La carga asíncrona es la práctica de fetchear recursos (scripts, stylesheets, imágenes, módulos código) sin bloquear el parsing, rendering o main thread de la página. Hecho bien puede afeitar segundos del page load — hecho mal causa layout shifts, race conditions y peor UX que la carga síncrona.
Técnicas carga async
| Técnica | Qué hace | Mejor para |
|---|---|---|
<script async> | Descargar en paralelo; ejecutar cuando ready | Scripts third-party independientes |
<script defer> | Descargar paralelo; ejecutar después parsing en orden | Scripts app que necesitan DOM ready |
<script type="module"> | Defer por default; imports ESM | Código app moderno |
<img loading="lazy"> | Diferir carga imagen hasta cerca viewport | Imágenes below-the-fold |
Dynamic import() | Cargar módulo JS on demand | Code splitting |
requestIdleCallback | Correr código durante idle navegador | Trabajo non-crítico |
| Web Workers | Ejecución JS background thread | Compute pesado |
fetch() + Promises | Requests HTTP async | Carga datos después render inicial |
async vs defer
<script src="app.js"></script>
<script async src="analytics.js"></script>
<script defer src="app.js"></script>| Aspecto | async | defer |
|---|---|---|
| Orden ejecución | Cualquiera carga primero | Orden documento |
| Ejecuta cuándo | En cuanto descargado | Después HTML parseado |
| ¿Bloquea parser? | No | No |
| ¿DOM ready? | Maybe not | Sí (siempre) |
| Mejor para | Scripts independientes | Código app que necesita DOM |
Lazy-loading imagen
<img src="hero.jpg" loading="eager" width="1200" height="600">
<img src="footer.jpg" loading="lazy" width="800" height="200">Dynamic imports para code splitting
button.addEventListener('click', async () => {
const { openModal } = await import('./modal');
openModal();
});Patterns carga datos async
async function loadUsers() {
const res = await fetch('/api/users');
return res.json();
}
const [users, posts] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json())
]);Mejores prácticas carga async
- Usar defer para scripts app.
- Usar async para analytics + ads.
- Lazy-load imágenes below-the-fold.
- Eager-load imagen LCP.
- Code-split routes.
- Promise.all para fetches concurrentes.
- Mostrar loading states.
- Manejar errores.
- Throttle/debounce ops async expensive.
Pitfalls comunes
- async en código app que necesita DOM.
- Lazy-load imagen above-the-fold.
- Awaits secuenciales cuando paralelo posible.
- Olvidar manejo errores en async.
- Sin loading state.
- Race conditions.
- Memory leaks de async no cancelado.
- Await bloqueante en critical path.
FAQ: carga asíncrona
¿async vs defer: cuál usar?
defer para tu código; async para third-party independiente.
¿Funciona lazy-loading en todos los navegadores?
Native loading="lazy": ~95%+.
¿Cómo afecta dynamic import al tamaño bundle?
Dramáticamente — código se splitea en chunks separados.
¿Debería lazy-load todas las imágenes?
No — solo below-the-fold.
¿Qué es race condition en código async?
Dos ops async terminan en orden inesperado.
¿Cómo cancelo un fetch async?
AbortController.
¿Diferencia entre Promise y async/await?
La misma cosa — async/await es syntactic sugar.
Testea impacto carga async con LoadFocus
LoadFocus corre auditorías Lighthouse desde 25+ regiones, midiendo LCP/INP/TBT. Regístrate en loadfocus.com/signup.
Herramientas LoadFocus relacionadas
Lleva este concepto a la práctica con LoadFocus — la misma plataforma que potencia todo lo que acabas de leer.