En el desarrollo web moderno, la gestión eficiente de los recursos es vital para garantizar una buena experiencia de usuario. Uno de los cuellos de botella más comunes es la carga de archivos JavaScript a través de la etiqueta <script>. El comportamiento por defecto de estas etiquetas puede ralentizar el renderizado de la página, por lo cual los atributos defer y async se vuelven herramientas fundamentales para los desarrolladores.
El proceso de carga predeterminado
Cuando un navegador encuentra una etiqueta <script src="..."> estándar, el motor de renderizado detiene inmediatamente la construcción del DOM (Document Object Model). El navegador debe solicitar el archivo al servidor, descargarlo y ejecutarlo antes de continuar con el resto del HTML. Este comportamiento se conoce como "bloqueante".
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Bloqueo del Renderizado</title>
</head>
<body>
<header>
<h1>Panel de Control</h1>
</header>
<!-- El navegador se detiene aquí hasta que el script se descargue y ejecute -->
<script src="proceso-pesado.js"></script>
<main>
<p>Este contenido no se verá hasta que el script termine.</p>
</main>
</body>
</html>
El atributo defer: Orden y post-procesamiento
El atributo defer indica al navegador que debe descargar el script en segundo plano sin interrumpir el aálisis del HTML. Sin embargo, la ejecución del script se pospone hasta que el documento ha sido completamente analizado por el navegador.
Características principales:
- Ejecución ordenada: Los scripts con
deferse ejecutan siguiendo estrictamente el orden en el que aparecen en el código HTML. - No bloqueante: El aálisis del DOM continúa mientras el archivo se descarga.
- Momento de ejecución: Se ejecutan justo antes del evento
DOMContentLoaded.
<!-- Ejemplo con múltiples dependencias -->
<script defer src="biblioteca-core.js"></script>
<script defer src="modulo-interfaz.js"></script>
<!--
Ambos se descargan en paralelo.
"biblioteca-core.js" siempre se ejecutará antes que "modulo-interfaz.js"
-->
El atributo async: Ejecución inmediata tras la descarga
Al igual que defer, el atributo async permite que la descarga del script ocurra de forma asíncrona. La diferencia fundamental radica en que, una vez terminada la descarga, el navegador pausará el análisis del HTML para ejecutar el script de inmediato.
Características principales:
- Orden independiente: El orden en el HTML no importa; el script que termine de descargarse primero será el primero en ejecutarse.
- Potencial de interrupción: Si el script se descarga antes de que el DOM esté listo, interrumpirá el análisis para ejecutarse.
- Ideal para terceros: Es perfecto para scripts que no dependen de otros archivos ni manipulan la estructura crítica del DOM.
<!-- Scripts independientes de analítica o publicidad -->
<script async src="https://metrics-service.com/tracker.js"></script>
<script async src="https://ads-provider.com/banner.js"></script>
<!--
Si "banner.js" es más pequeño que "tracker.js",
se ejecutará primero, sin importar su posición.
-->
Comparativa de flujos de trabajo
Para elegir la estrategia adecuada, considere la siguiente tabla técnica:
| Atributo | Descarga | Ejecución | Garantiza Orden |
|---|---|---|---|
| Ninguno | Bloqueante | Inmediata | Sí (secuencial) |
| defer | Asíncrona | Al finalizar el parsing del HTML | Sí |
| async | Asíncrona | Inmediata tras descargar | No |
Criterios de selección en el desarrollo real
La elección entre estas opciones depende de la naturaleza del código:
- Uso de
defer: Es la opción recomendada para la lógica principal de la aplicación. Si su script necesita interactuar con elementos del DOM (como añadir eventos a botones) o si un script depende de otro (como un plugin de una librería base),deferasegura que todo esté disponible y en orden. - Uso de
async: Utilícelo para herramientas externas que funcionan de manera aislada. Los scripts de seguimiento de usuarios, contadores de visitas o servicios de chat son candidatos ideales, ya que su ejecución temprana no afecta la lógica de negocio del sitio.
Es importante recordar que ambos atributos solo tienen efecto cuando el script posee un origen externo mediante el atributo src. En scripts internos (inline), estos atributos son ignorados por los navegadores estándar.