• La posición importa
  • Async y Defer
  • Comparación de rendimiento
    • Sin defer ni async, en la cabeza
    • Sin defer ni async, en el cuerpo
    • Con async, en la cabeza
    • Con defer, en la cabeza
  • Bloqueando el parsing
  • Bloqueando el renderizado
  • domInteractive
  • Manteniendo las cosas en orden
  • Sólo dime la mejor manera

Cuando se carga un script en una página HTML, hay que tener cuidado de no perjudicar el rendimiento de carga de la página.

Tradicionalmente, un script se incluye en la página de esta manera:

<script src="https://flaviocopes.com/javascript-async-defer/script.js"></script>

Cuando el analizador HTML encuentre esta línea, se hará una petición para obtener el script, y éste se ejecutará.

Una vez realizado este proceso, el parsing puede reanudarse, y el resto del HTML puede ser analizado.

Como puedes imaginar, esta operación puede tener un gran impacto en el tiempo de carga de la página.

Si el script tarda un poco más en cargarse de lo esperado, por ejemplo si la red es un poco lenta o si estás en un dispositivo móvil y la conexión es un poco descuidada, el visitante probablemente verá una página en blanco hasta que el script se cargue y ejecute.

La posición importa

Cuando aprendes HTML por primera vez, te dicen que las etiquetas de script viven en la etiqueta <head>:

<html> <head> <title>Title</title> <script src="https://flaviocopes.com/javascript-async-defer/script.js"></script> </head> <body> ... </body></html>

Como te dije antes, cuando el analizador encuentra esta línea, va a buscar el script y lo ejecuta. Luego, cuando termina con esta tarea, pasa a analizar el cuerpo.

Esto es malo porque se introduce mucho retraso. Una solución muy común a este problema es poner la etiqueta script al final de la página, justo antes de la etiqueta de cierre </body>.

Al hacer esto, el script se carga y se ejecuta después de que toda la página ya esté analizada y cargada, lo que supone una gran mejora respecto a la alternativa head.

Esto es lo mejor que puedes hacer si necesitas dar soporte a los navegadores más antiguos que no soportan dos características relativamente recientes de HTML: async y defer.

Async y Defer

Tanto async como defer son atributos booleanos. Su uso es similar:

<script async src="https://flaviocopes.com/javascript-async-defer/script.js"></script>
<script defer src="https://flaviocopes.com/javascript-async-defer/script.js"></script>

Si especifica ambos, async tiene prioridad en los navegadores modernos, mientras que los navegadores más antiguos que soportan defer pero no async volverán a defer.

Estos atributos sólo tienen sentido cuando se utiliza el script en la parte head de la página, y son inútiles si se pone el script en el pie de página body como vimos anteriormente.

Comparación de rendimiento

Sin defer ni async, en la cabecera

Así es como una página carga un script sin defer ni async, puesto en la porción head de la página:

El análisis sintáctico se detiene hasta que se obtiene el script, y se ejecuta. Una vez hecho esto, el análisis sintáctico se reanuda.

Sin defer o async, en el cuerpo

Así es como una página carga un script sin defer o async, puesto al final de la etiqueta body, justo antes de que se cierre:

El análisis sintáctico se hace sin ninguna pausa, y cuando termina, el script se obtiene, y se ejecuta. El análisis sintáctico se realiza antes de que se descargue el script, por lo que la página aparece al usuario mucho antes que en el ejemplo anterior.

Con async, en el head

Así es como una página carga un script con async, puesto en la etiqueta head:

El script se obtiene de forma asíncrona, y cuando está listo el parseo del HTML se pausa para ejecutar el script, y luego se reanuda.

Con defer, en el head

Así es como una página carga un script con defer, puesto en la etiqueta head:

El script se obtiene de forma asíncrona, y se ejecuta sólo después de que el análisis de HTML está hecho.

El análisis sintáctico termina igual que cuando ponemos el script al final de la etiqueta body, pero en general la ejecución del script termina mucho antes, porque el script se ha descargado en paralelo con el análisis sintáctico del HTML.

Así que esta es la solución ganadora en términos de velocidad 🏆

Bloqueo del parsing

async bloquea el parsing de la página mientras que defer no lo hace.

Bloqueo del rendering

Ni async ni defer garantizan nada en el bloqueo del rendering. Esto depende de ti y de tu script (por ejemplo, asegurándote de que tus scripts se ejecutan después del evento onLoad).

domInteractive

Los scripts marcados con defer se ejecutan justo después del evento domInteractive, que ocurre después de que el HTML se cargue, se analice y se construya el DOM.

El CSS y las imágenes en este punto aún deben ser analizadas y cargadas.

Una vez hecho esto, el navegador emitirá el evento domComplete, y luego onLoad.

domInteractiveEs importante porque su tiempo es reconocido como una medida de la velocidad de carga percibida. Ver el MDN para más.

Mantener las cosas en orden

Otro caso pro defer: los scripts marcados async se ejecutan en orden casual, cuando están disponibles. Los scripts marcados con defer se ejecutan (una vez completado el análisis sintáctico) en el orden en que están definidos en el marcado.

Dime cuál es la mejor manera

Lo mejor que puedes hacer para acelerar la carga de tu página cuando usas scripts es ponerlos en el head, y añadir un atributo defer a tu etiqueta script:

<script defer src="https://flaviocopes.com/javascript-async-defer/script.js"></script>

Este es el escenario que activa el evento domInteractive más rápido.

Considerando los pros de defer, parece una mejor opción sobre async en una variedad de escenarios.

A menos que usted está bien con el retraso de la primera representación de la página, asegúrese de que cuando la página se analiza el JavaScript que desea ya se ejecuta.

Descargue mi manual gratuito para principiantes de JavaScript

Más tutoriales para navegadores:

  • Algunos trucos útiles disponibles en HTML5
  • Cómo hice que un sitio web basado en CMS-basado en un CMS funcionara sin conexión
  • La guía completa de las aplicaciones web progresivas
  • La API Fetch
  • La guía de la API Push
  • El canal de mensajería API
  • Tutorial de Service Workers
  • Guía de la API de Caché
  • Guía de la API de Notificación
  • Sumérgete en IndexedDB
  • La API de Selectores: querySelector y querySelectorAll
  • Carga eficiente de JavaScript con defer y async
  • El modelo de objetos del documento (DOM)
  • La API de almacenamiento web: almacenamiento local y almacenamiento de sesión
  • Aprende cómo funcionan las cookies HTTP
  • La API de historial
  • El formato de imagen WebP
  • XMLHttpRequest (XHR)
  • Un tutorial en profundidad sobre SVG
  • Qué son las URL de datos
  • Mapa de ruta para aprender la Plataforma Web
  • CORS, Cross-Origin Resource Sharing
  • Web Workers
  • La guía requestAnimationFrame()
  • Qué es el Doctype
  • Trabajar con la DevTools Console y la API Console
  • La API Speech Synthesis
  • Cómo esperar el evento DOM ready en JavaScript plano
  • Cómo añadir una clase a un
  • Cómo hacer un bucle sobre los elementos del DOM desde querySelectorAll
  • Cómo eliminar una clase de un elemento del DOM
  • Cómo comprobar si un elemento del DOM tiene una clase
  • Cómo cambiar el valor de un nodo del DOM
  • Cómo añadir un evento de clic a una lista de elementos del DOM devueltos desde querySelectorAll
  • WebRTC, la API web en tiempo real
  • Cómo obtener la posición de desplazamiento de un elemento en JavaScript
  • Cómo reemplazar un elemento DOM
  • Cómo aceptar sólo imágenes en un campo de archivo de entrada
  • ¿Por qué utilizar una versión de vista previa de un navegador?
  • El objeto Blob
  • El objeto File
  • El objeto FileReader
  • El objeto FileList
  • ArrayBuffer
  • ArrayBufferView
  • El objeto URL
  • Tipos Arrays
  • El objeto DataView
  • La API BroadcastChannel
  • La API Streams
  • El objeto FormData
  • El objeto Navigator
  • Cómo utilizar la API Geolocalización
  • Cómo utilizar getUserMedia()
  • Cómo utilizar la API de arrastrar y soltar
  • Cómo trabajar con el desplazamiento en las páginas web
  • Manejar formularios en JavaScript
  • Eventos de teclado
  • Mouse eventos
  • Eventos táctiles
  • ¿Cómo eliminar todos los hijos de un elemento DOM
  • Cómo crear un atributo HTML usando Javascript de vainilla
  • Cómo comprobar si una casilla de verificación está marcada usando JavaScript?
  • ¿Cómo copiar al portapapeles usando JavaScript
  • Cómo desactivar un botón usando JavaScript
  • Cómo hacer una página editable en el navegador
  • Cómo obtener valores de cadenas de consulta en JavaScript con URLSearchParams
  • Cómo eliminar todo el CSS de una página de una vez
  • Cómo usar insertAdjacentHTML
  • Safari, avisar antes de salir
  • Cómo añadir una imagen al DOM usando JavaScript
  • Cómo reiniciar un formulario
  • Cómo usar Google Fonts

.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.