¿Cuál es la diferencia entre los atributos async y defer en JavaScript?

¿Cuál es la diferencia entre los atributos async y defer en JavaScript?

Hoy en día, la optimización de los tiempos de carga de tu página web es muy importante en muchos aspectos. Si tu sitio web se carga lentamente, Google no clasificará tu sitio web muy bien y, por lo tanto, los usuarios, ya que probablemente no volverán a una página web que tarda unos minutos en cargarse correctamente para lo realmente importante que están buscando, la información. Debes tener en cuenta que no todos tienen acceso a conexiones de alta velocidad, Sudamérica es el mejor ejemplo de esta situación. En los países desarrollados la historia es totalmente diferente, sin embargo, tampoco debes olvidar a las personas con conexiones móviles (4G) que aunque es rápido, a veces no es tan rápido como cabría esperar.

En una página web, los elementos de script ( <script src="somescript.js"></script>) suelen ser los recursos más comunes que bloquean directamente la representación y el análisis del documento HTML. El navegador, cuando comienza a analizar el HTML y encuentra una etiqueta de secuencia de comandos, espera la descarga de la secuencia de comandos y la ejecuta, solo entonces, procesa el resto de la página. 

Afortunadamente para el usuario, existen 2 atributos para la etiqueta de script que pueden ayudar a resolver este problema, específicamente defer async.

A. <script>

Incluir un script sin async o defer es la forma predeterminada de cargar scripts en el documento HTML. A través de este método:

<script src="somescript.js"></script>

Cuando el analizador HTML procesa esta etiqueta, se ejecutará una nueva solicitud para recuperar el archivo somescript.js en el servidor. Una vez que finaliza la descarga, el script se ejecuta inmediatamente. Tan pronto como se ejecuta, el analizador HTML analiza el resto del documento. Esto es especialmente dañino cuando los desarrolladores colocan sus scripts en la etiqueta head:

<html lang="en-US">
    <head>
        <title>Our Code World</title>
        <script src="somescript.js"></script>
    </head>

    <body>
        <h3>Hello World!</h3>
        ...
    </body>
</html>

Entonces, hasta que el usuario pueda ver ese título, habrá pasado un buen rato. Puedes comprender gráficamente este comportamiento con el siguiente gráfico:

Script Default Loading Waterfall

B. <script async>

Al incluir un script con el atributo async, el script se descarga en paralelo con la interpretación del HTML. Cuando se descarga el script, se ejecuta, bloqueando el renderizado hasta que finaliza.

En este enfoque, el orden de ejecución de los scripts no está garantizado, ya que dependería totalmente de cuál se descargue primero, que puede variar a veces. Entonces, por ejemplo, si carga los siguientes scripts en el mismo orden:

  • script1.js
  • script2.js
  • script3.js

A veces, la ejecución variaría:

  • script2.js
  • script1.js
  • script3.js

Entonces, idealmente, al usar async, los scripts no deberían depender entre sí o las cosas se complicarán. Puede comprender gráficamente este comportamiento con el siguiente gráfico:

JavaScript Include Async Script

C. <script defer>

Finalmente, el script diferido se descargará de forma asincrónica y en paralelo con el análisis de HTML, sin embargo, su ejecución se aplaza hasta que se haya analizado todo el documento HTML. En este caso, si se cargan varios scripts, se respetará el mismo orden de carga al ejecutarlo.

Puede comprender gráficamente este comportamiento con el siguiente gráfico:

JavaScript Include Deferred Script

Entonces, ¿cuál es el mejor?

¡Eso depende!

Lo sé, es el tipo de respuesta que encontrará en todas partes si se hace esta pregunta. Debe saber que ni async ni defer garantizan que no se bloquee la renderización, ya que al final de todo, depende de usted y su script.

Bueno, implementar async o diferir hará que sus tiempos de carga sean automáticamente mejores que antes (si se implementan correctamente). Sin embargo, hay una estructura interesante que aunque no se ve bien a los ojos de nuestro programador, sí se comporta de manera bastante óptima en redes lentas:

<html lang="en-US">
    <head>
        <title>Our Code World</title>

        <!-- 1. Load CSS -->
        <link href="stylesheet1.css" rel="stylesheet">
        <link href="stylesheet2.css" rel="stylesheet">

        <!-- 2. Load Deferred JS -->
        <script src="script1.js" defer></script>
        <script src="script2.js" defer></script>
        <script src="script3.js" defer></script>
    </head>
    <body>
        <!-- In this way the user will be able to access the content of the article way faster than usual -->
        <h3>Article Title</h3>
        <p>This is the important content that I want to see, not fancy menus or ads!</p>
    </body>
</html>

Así es, incluir el script diferido en la etiqueta principal del documento se comportará mucho más rápido para los usuarios con conexiones lentas. De acuerdo con las siguientes pruebas, cargar nuestro propio blog (ourcodeworld.com con un tamaño de aproximadamente 700KB de CSS y JavaScript) con diferentes velocidades de conexión mostró los siguientes resultados para el domInteractiveevento (esta propiedad se puede usar para medir la velocidad de carga de sitios web que los usuarios sienten):

# Test (Velocidad) Script diferido en tag head Script diferido al final de body
#1 (30KB/s) 50 Seconds 1 Minute 41 Seconds
#2 (150KB/s) 16 Seconds 27 Seconds
#3 (500KB/s) 3.7 Seconds 6.3 Seconds
#4 (2000KB/s) 1.89 Seconds 1.75 Seconds

Como puedes ver, el enfoque de cargar los scripts diferidos en head permite que el evento domInteractive se presente más rápido, por lo que en el caso de nuestro blog, los usuarios con las velocidades mencionadas verán el contenido de los artículos en el tiempo que esta prueba. muestra. Puede ver esta tabla representada en el siguiente cuadro:

DomInteractive Deferred Scripts

Como otra conclusión, de esta prueba, puede notar que cuanto mayor es la velocidad de conexión a Internet, menos importante es la posición de los scripts diferidos, sin embargo, hay una mejora visible con velocidades de conexión más lentas.

El problema con este enfoque es que, aunque funciona increíblemente bien con una página web como un blog, implementar el mismo enfoque en algo como una aplicación de una sola página como React o Vue.js no tendría sentido, ¿no? Es por eso que utilizan el enfoque predeterminado de incluir JavaScript al final de la etiqueta del cuerpo.

Conclusiones

  • Los scripts marcados con deferse ejecutan justo después del evento domInteractive, que ocurre después de que el HTML se carga, analiza y se monta el DOM. Una vez hecho esto, el navegador emitirá el evento domComplete y luego onLoad.
  • Async y defer son básicamente dos atributos booleanos para la etiqueta <script>. Async permite la ejecución de scripts de forma asincrónica tan pronto como se descargan. Aplazar permite la ejecución solo después de que se haya analizado todo el documento.
  • Ambos atributos no tienen ningún efecto en los scripts en línea.

Que te diviertas ❤️!

Esto podria interesarte

Conviertete en un programador más sociable