Etiqueta de script - asíncrono y aplazar

548

Tengo un par de preguntas sobre los atributos asyncy deferla <script>etiqueta que, a mi entender, solo funcionan en los navegadores HTML5.

Uno de mis sitios tiene dos archivos JavaScript externos que actualmente se encuentran justo encima de la </body>etiqueta; el primero es proviene de google y el segundo es un script externo local.

Con respecto a la velocidad de carga del sitio

  1. ¿Hay alguna ventaja en agregar asynca los dos scripts que tengo al final de la página?

  2. ¿Sería ventajoso agregar la asyncopción a los dos scripts y colocarlos en la parte superior de la página en el <head>?

  3. ¿Significaría esto que se descargan cuando se carga la página?
  4. Supongo que esto causaría retrasos en los navegadores HTML4, pero ¿aceleraría la carga de la página para los navegadores HTML5?

Utilizando <script defer src=...

  1. ¿Cargar los dos scripts dentro <head>con el atributo deferafectaría lo mismo que tener los scripts antes </body>?
  2. Una vez más, supongo que esto ralentizaría los navegadores HTML4.

Utilizando <script async src=...

Si tengo dos scripts con asynchabilitado

  1. ¿Se descargarían al mismo tiempo?
  2. ¿O uno a la vez con el resto de la página?
  3. ¿El orden de los scripts se convierte en un problema? Por ejemplo, un script depende del otro, por lo que si uno se descarga más rápido, el segundo podría no ejecutarse correctamente, etc.

Finalmente, ¿es mejor dejar las cosas como están hasta que HTML5 se use más comúnmente?

Adán
fuente
55
asynces nuevo (ish), pero deferha sido parte de IE desde IE4. deferse agregó a otros navegadores mucho más recientemente, pero las versiones anteriores de esos navegadores tienden a quedarse mucho menos.
Alohci
3
¡Ahora, HTML5 se ha vuelto muy popular!
sept08
2
deferes lo mismo que colocar scripts en la parte inferior del HTML, que ha sido común durante muchos años.
vsync
1
@vsync no es necesariamente cierto, el navegador descargará el JS con la etiqueta de aplazamiento cuando analiza la etiqueta del script, pero diferirá la ejecución hasta justo antes de DOMContentLoaded. La descarga es sin bloqueo. Colocar en la parte inferior del HTML retrasará la descarga y la ejecución del JS hasta que se construya el DOM, pero aún incurrirá en un retraso adicional al esperar la descarga.
Brad Frost el
@BradFrost: la descarga es un bloqueo en mi opinión, en el sentido de que está tomando ancho de banda de Internet, y para aquellos con conexión lenta, veo que es imperativo cargar primero el documento y solo entonces, cuando se haya procesado, comenzar a descargar archivos javascript . Esto es cierto en los casos en que el contenido no está estrechamente acoplado a JavaScript para representar todo (como SPA )
vsync

Respuestas:

406

Mantenga sus guiones justo antes </body>. Async se puede usar con scripts ubicados allí en algunas circunstancias (vea la discusión a continuación). Aplazar no hará una gran diferencia para los scripts ubicados allí porque el trabajo de análisis DOM ya se ha hecho de todos modos.

Aquí hay un artículo que explica la diferencia entre asíncrono y diferir: http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/ .

Su HTML se mostrará más rápido en navegadores antiguos si mantiene las secuencias de comandos al final del cuerpo justo antes </body>. Por lo tanto, para preservar la velocidad de carga en los navegadores más antiguos, no desea colocarlos en ningún otro lugar.

Si su segunda secuencia de comandos depende de la primera secuencia de comandos (por ejemplo, su segunda secuencia de comandos usa el jQuery cargado en la primera secuencia de comandos), entonces no puede hacerlos asíncronos sin un código adicional para controlar el orden de ejecución, pero puede hacerlos diferir porque diferirán las secuencias de comandos aún se ejecutará en orden, solo hasta que se haya analizado el documento. Si tiene ese código y no necesita que los scripts se ejecuten de inmediato, puede hacerlos asíncronos o diferirlos.

Puede colocar las secuencias de comandos en la <head>etiqueta y configurarlas, defery la carga de las secuencias de comandos se diferirá hasta que se haya analizado el DOM y se obtenga una visualización rápida de la página en los nuevos navegadores que admiten diferir, pero no lo ayudará en absoluto en navegadores antiguos y no es realmente más rápido que simplemente poner los scripts justo antes, lo </body>que funciona en todos los navegadores. Entonces, puedes ver por qué es mejor ponerlos justo antes </body>.

Async es más útil cuando realmente no te importa cuando se carga el script y nada más que depende del usuario depende de la carga de ese script. El ejemplo más citado para usar async es un script de análisis como Google Analytics que no desea que espere nada y no es urgente ejecutarlo pronto y está solo, por lo que nada más depende de ello.

Por lo general, la biblioteca jQuery no es un buen candidato para la sincronización porque otros scripts dependen de ella y desea instalar controladores de eventos para que su página pueda comenzar a responder a los eventos del usuario y es posible que deba ejecutar un código de inicialización basado en jQuery para establecer el estado inicial de la página. Se puede usar de forma asíncrona, pero habrá que codificar otros scripts para que no se ejecuten hasta que se cargue jQuery.

jfriend00
fuente
8
Defer debe ejecutarlos en orden todavía, pero ejecutar antes de dom-contentloaded. ¿Eso no significa que ponerlo en la cabeza sería más rápido, ya que puede comenzar a descargarlos ANTES de analizar el HTML del cuerpo?
Kevin
99
Dijiste que poner scripts heady configurarlos deferno será más rápido que ponerlos antes </body>, pero por lo que he leído, eso es incorrecto. Piénselo: si coloca los scripts <head>, comenzarán a descargarse inmediatamente, mientras que si son correctos antes </body>, todos los demás elementos se descargarán primero.
Nate
12
@Nate: no hará que su documento se cargue más rápido, que es mi punto. Tiene razón en que podría mejorar la carga de la secuencia de comandos antes, pero también podría ralentizar la carga del documento y su contenido porque está utilizando parte de su ancho de banda y una de las conexiones limitadas que el navegador hará a un servidor determinado para cargar el script mientras también intenta cargar su contenido.
jfriend00
44
"Si su segundo script depende del primer script ... entonces no puede hacerlos asíncronos o diferidos", eso no es cierto, con diferir se ejecutan en orden.
DisgruntledGoat
2
En este punto, el requisito </body> no es realmente necesario con los desarrollos del navegador desde 2012 cuando se publicó esta respuesta.
bgcode
845

Esta imagen explica la etiqueta de script normal, asíncrono y aplazar

ingrese la descripción de la imagen aquí

  • Las secuencias de comandos asíncronas se ejecutan tan pronto como se carga la secuencia de comandos, por lo que no garantiza el orden de ejecución (una secuencia de comandos que incluyó al final puede ejecutarse antes del primer archivo de secuencia de comandos)

  • Aplazar scripts garantiza el orden de ejecución en el que aparecen en la página.

Ref. Este enlace: http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html

Prasanth Bendra
fuente
Creo que un ejemplo con múltiples scripts habría sido mejor para ilustrar su secuencia
vsync
44
@writofmandamus Parece asyncque ganará. Ver stackoverflow.com/questions/13821151/…
Monseñor
Gracias por la buena explicación. Sin embargo, las imágenes no están a escala. En el caso de solo la <script>etiqueta, la longitud total de la carga de la página es mayor por el tiempo que lleva descargar el archivo de script.
arni
@BhavikHirani De acuerdo con este sitio , el uso de asíncrono y diferir en la misma etiqueta de script usa asíncrono si el navegador lo admite, o recurre a diferir si no admite asíncrono, pero admite diferir. Los comportamientos son bastante diferentes, por lo que no recomendaría usar ambos, ya que el resultado es impredecible y puede ser una gran fuente de errores.
Adrian Wiik
@arni Solo si el ancho de banda se utiliza por completo, lo cual rara vez se utiliza. Y ambas descargas compartirían el ancho de banda, no bloquearían una. Además: estas imágenes muestran el análisis en verde, no la descarga.
Robert Siemer
213

HTML5: async,defer

En HTML5, puede decirle al navegador cuándo ejecutar su código JavaScript. Hay 3 posibilidades:

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

<script async src="myscript.js"></script>

<script defer src="myscript.js"></script>
  1. Sin asynco defer, el navegador ejecutará su secuencia de comandos inmediatamente, antes de representar los elementos que están debajo de su etiqueta de secuencia de comandos.

  2. Con async(asíncrono), el navegador continuará cargando la página HTML y la procesará mientras el navegador carga y ejecuta el script al mismo tiempo.

  3. Con defer, el navegador ejecutará su script cuando la página termine de analizarse. (no es necesario terminar de descargar todos los archivos de imagen. Esto es bueno).

Dinesh
fuente
Se requiere la plantilla blogger.com async=""antes de validar y guardar los cambios de plantilla.
noobninja
1
Nota: no hay garantía de que los scripts se ejecuten en el orden en que se especifican mediante Async. "Entonces, si su segundo script depende del primer script, evite Async".
Faisal Naseer
2
async- Las secuencias de comandos se ejecutan en el momento en que se han descargado, sin tener en cuenta su orden en el archivo HTML.
vsync
30

Ambos asyncy los deferscripts comienzan a descargarse inmediatamente sin pausar el analizador y ambos admiten una opciónonload controlador para abordar la necesidad común de realizar la inicialización que depende del script.

La diferencia entre asyncy se defercentra alrededor cuando se ejecuta el script. Cada asyncsecuencia de comandos se ejecuta en la primera oportunidad después de que finaliza la descarga y antes del evento de carga de la ventana. Esto significa que es posible (y probable) que los asyncscripts no se ejecuten en el orden en que aparecen en la página. Mientras que los deferscripts, por otro lado, están garantizados para ejecutarse en el orden en que aparecen en la página. Esa ejecución comienza después de que el análisis se haya completado por completo, pero antes del DOMContentLoadedevento del documento .

Fuente y más detalles: aquí .

Zameer Khan
fuente
25

Enfrenté el mismo tipo de problema y ahora entendí claramente cómo funcionarán ambos. Espero que este enlace de referencia sea útil ...

Asíncrono

Cuando agrega el atributo asíncrono a su etiqueta de script, sucederá lo siguiente.

<script src="myfile1.js" async></script>
<script src="myfile2.js" async></script>
  1. Realice solicitudes paralelas para recuperar los archivos.
  2. Continúe analizando el documento como si nunca se hubiera interrumpido.
  3. Ejecute los scripts individuales en el momento en que se descargan los archivos.

Aplazar

El aplazamiento es muy similar al asíncrono con una diferencia importante. Esto es lo que sucede cuando un navegador encuentra un script con el atributo de aplazamiento.

<script src="myfile1.js" defer></script>
<script src="myfile2.js" defer></script>
  1. Realice solicitudes paralelas para recuperar los archivos individuales.
  2. Continúe analizando el documento como si nunca se hubiera interrumpido.
  3. Termine de analizar el documento incluso si los archivos de script se han descargado.
  4. Ejecute cada secuencia de comandos en el orden en que se encontraron en el documento.

Referencia: Diferencia entre Async y Defer

kamesh
fuente
7

asyncy deferdescargará el archivo durante el análisis HTML. Ambos no interrumpirán el analizador.

  • El script con asyncatributo se ejecutará una vez que se haya descargado. Mientras que el script con deferatributo se ejecutará después de completar el análisis DOM.

  • Los scripts cargados con asyncno garantizan ningún orden. Mientras que los scripts cargados con deferatributo mantienen el orden en que aparecen en el DOM.

Úselo <script async>cuando el script no se base en nada. cuando la secuencia de comandos depende de su uso.

La mejor solución sería agregar la parte inferior del cuerpo. No habrá problemas con el bloqueo o el renderizado.

NavyaKumar
fuente
Solo quiero hacer algunas aclaraciones aquí, dos cosas están sucediendo aquí 1. Descarga del recurso 2. Ejecución del recurso. La descarga de recursos en ambos casos (asíncrono y diferido) no está bloqueando, es decir, no bloquea el análisis de html, mientras que la ejecución en asíncrono bloquea el análisis y, en caso de diferir, la ejecución se lleva a cabo después de analizar el marcado html, por lo tanto no bloqueo en este caso.
pOoOf
5

Creo que Jake Archibald nos presentó algunas ideas en 2013 que podrían agregar aún más positividad al tema:

https://www.html5rocks.com/en/tutorials/speed/script-loading/

El Santo Grial está descargando un conjunto de scripts de inmediato sin bloquear el renderizado y ejecutarlo lo antes posible en el orden en que se agregaron. Lamentablemente, HTML te odia y no te permitirá hacerlo.

(...)

La respuesta está realmente en la especificación HTML5, aunque está oculta en la parte inferior de la sección de carga de scripts. " El atributo IDL asíncrono controla si el elemento se ejecutará asíncronamente o no. Si se establece el indicador" force-async "del elemento, entonces, al obtener, el atributo IDL asíncrono debe devolver verdadero, y al configurar," force-async " la bandera primero debe estar desarmada ... ".

(...)

Las secuencias de comandos que se crean dinámicamente y se agregan al documento son asíncronas de forma predeterminada , no bloquean el procesamiento y se ejecutan tan pronto como se descargan, lo que significa que podrían salir en el orden incorrecto. Sin embargo, podemos marcarlos explícitamente como no asíncronos:

[
    '//other-domain.com/1.js',
    '2.js'
].forEach(function(src) {
    var script = document.createElement('script');
    script.src = src;
    script.async = false;
    document.head.appendChild(script);
});

Esto le da a nuestros scripts una combinación de comportamiento que no se puede lograr con HTML simple. Al ser explícitamente no asíncrono, los scripts se agregan a una cola de ejecución, la misma cola a la que se agregan en nuestro primer ejemplo de HTML sin formato. Sin embargo, al crearse dinámicamente, se ejecutan fuera del análisis de documentos, por lo que el procesamiento no se bloquea mientras se descargan (no confunda la carga de scripts no asíncronos con XHR de sincronización, que nunca es algo bueno).

La secuencia de comandos anterior se debe incluir en línea en el encabezado de las páginas, poniendo en cola las descargas de secuencias de comandos lo antes posible sin interrumpir el procesamiento progresivo, y se ejecuta tan pronto como sea posible en el orden especificado. "2.js" se puede descargar gratis antes de "1.js", pero no se ejecutará hasta que "1.js" se haya descargado y ejecutado con éxito, o no lo haga. ¡Hurra! descarga asincrónica pero ejecución ordenada !

Aún así, esta podría no ser la forma más rápida de cargar scripts:

(...) Con el ejemplo anterior, el navegador tiene que analizar y ejecutar el script para descubrir qué scripts descargar. Esto oculta sus scripts de los escáneres de precarga. Los navegadores usan estos escáneres para descubrir recursos en las páginas que probablemente visitará a continuación, o descubrir recursos de la página mientras el analizador está bloqueado por otro recurso.

Podemos agregar de nuevo la capacidad de descubrimiento al poner esto en el encabezado del documento:

<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">

Esto le dice al navegador que la página necesita 1.js y 2.js. link [rel = subresource] es similar a link [rel = prefetch], pero con semántica diferente. Desafortunadamente, actualmente solo es compatible con Chrome, y debe declarar qué scripts cargar dos veces, una vez a través de elementos de enlace y otra vez en su script.

Corrección: Originalmente dije que estos fueron recogidos por el escáner de precarga, no son, son recogidos por el analizador regular. Sin embargo, el escáner de precarga podría recogerlos, todavía no lo hace, mientras que las secuencias de comandos incluidas en el código ejecutable nunca se pueden precargar. Gracias a Yoav Weiss que me corrigió en los comentarios.

mjfneto
fuente
1

Parece que el comportamiento de diferir y asincrónico depende del navegador, al menos en la fase de ejecución. NOTA: diferir solo se aplica a scripts externos. Supongo que async sigue el mismo patrón.

En IE 11 y versiones posteriores, el orden parece ser así:

  • asíncrono (podría ejecutarse parcialmente mientras se carga la página)
  • ninguno (podría ejecutarse mientras se carga la página)
  • diferir (se ejecuta después de cargar la página, diferir todos en orden de ubicación en el archivo)

En Edge, Webkit, etc., el atributo asíncrono parece ignorarse o colocarse al final:

  • data-pagespeed-no-defer (se ejecuta antes que cualquier otro script, mientras se carga la página)
  • ninguno (podría ejecutarse mientras se carga la página)
  • diferir (espera hasta que DOM se cargue, todos difieren en orden de ubicación en el archivo)
  • asíncrono (parece esperar hasta que DOM se cargue)

En los navegadores más nuevos, el atributo data-pagespeed-no-defer se ejecuta antes que cualquier otro script externo. Esto es para scripts que no dependen del DOM.

NOTA: Use aplazar cuando necesite un orden explícito de ejecución de sus scripts externos. Esto le dice al navegador que ejecute todos los scripts diferidos en orden de ubicación en el archivo.

A UN LADO: El tamaño de los javascripts externos importó al cargar ... pero no tuvo ningún efecto en el orden de ejecución.

Si le preocupa el rendimiento de sus scripts, es posible que desee considerar la minificación o simplemente cargarlos dinámicamente con un XMLHttpRequest.

Charles Owen
fuente
data-pagespeed-no-deferes un atributo utilizado por el módulo PageSpeed ​​del lado del servidor . El atributo por sí mismo no tiene ningún efecto en ningún navegador. data-pagespeed-no-defer
Qtax