Hay muchas maneras diferentes de incluir JavaScript en una página html. Conozco las siguientes opciones:
- código en línea o cargado desde URI externo
- incluido en la etiqueta <head> o <body> [ 1 , 2 ]
- sin ninguno
defer
oasync
atributo (solo scripts externos) - incluido en fuente estática o agregado dinámicamente por otros scripts (en diferentes estados de análisis, con diferentes métodos)
Sin contar las onEvent
secuencias de comandos del navegador desde el disco duro, javascript: URI y -atributos [ 3 ], ya hay 16 alternativas para ejecutar JS y estoy seguro de que olvidé algo.
No estoy tan preocupado por la carga rápida (paralela), tengo más curiosidad sobre el orden de ejecución (que puede depender del orden de carga y el orden del documento ). ¿Existe una buena referencia (navegador cruzado) que cubra realmente todos los casos? Por ejemplo, http://www.websiteoptimization.com/speed/tweak/defer/ solo trata con 6 de ellos y prueba principalmente navegadores antiguos.
Como me temo que no, aquí está mi pregunta específica: tengo algunos guiones de cabeza (externos) para la inicialización y la carga de guiones. Luego tengo dos scripts estáticos en línea al final del cuerpo. El primero permite que el cargador de scripts agregue dinámicamente otro elemento de scripts (haciendo referencia a js externos) al cuerpo. El segundo de los scripts estáticos en línea quiere usar js del script externo agregado. ¿Puede confiar en que el otro haya sido ejecutado (y por qué :-)?
fuente
Respuestas:
Si no carga dinámicamente los scripts o los marca como
defer
oasync
, los scripts se cargan en el orden que se encuentran en la página. No importa si se trata de un script externo o un script en línea: se ejecutan en el orden en que se encuentran en la página. Los scripts en línea que vienen después de los scripts externos se mantienen hasta que todos los scripts externos que vinieron antes que ellos se hayan cargado y ejecutado.Las secuencias de comandos asíncronas (independientemente de cómo se especifiquen como asíncronas) se cargan y ejecutan en un orden impredecible. El navegador los carga en paralelo y es libre de ejecutarlos en el orden que desee.
No hay un orden predecible entre varias cosas asíncronas. Si se necesitara un orden predecible, entonces tendría que codificarse al registrarse para recibir notificaciones de carga de los scripts asíncronos y secuenciar manualmente las llamadas de JavaScript cuando se cargan las cosas apropiadas.
Cuando una etiqueta de script se inserta dinámicamente, el comportamiento del orden de ejecución dependerá del navegador. Puedes ver cómo se comporta Firefox en este artículo de referencia . En pocas palabras, las versiones más recientes de Firefox predeterminan una etiqueta de secuencia de comandos agregada dinámicamente a asíncrono a menos que la etiqueta de secuencia de comandos se haya establecido de otra manera.
Una etiqueta de script con
async
puede ejecutarse tan pronto como se cargue. De hecho, el navegador puede pausar el analizador de cualquier otra cosa que esté haciendo y ejecutar ese script. Por lo tanto, realmente puede ejecutarse en casi cualquier momento. Si el script se almacenó en caché, podría ejecutarse casi de inmediato. Si el script tarda un tiempo en cargarse, podría ejecutarse después de que se complete el analizador. Una cosa para recordarasync
es que puede ejecutarse en cualquier momento y que el tiempo no es predecible.Una etiqueta de secuencia de comandos
defer
espera hasta que se complete el analizador completo y luego ejecuta todas las secuencias de comandos marcadasdefer
en el orden en que se encontraron. Esto le permite marcar varios scripts que dependen unos de otros comodefer
. Todos se pospondrán hasta que finalice el analizador de documentos, pero se ejecutarán en el orden en que se encontraron preservando sus dependencias. Pienso quedefer
los scripts se colocan en una cola que se procesará después de que se complete el analizador. Técnicamente, el navegador puede estar descargando los scripts en segundo plano en cualquier momento, pero no ejecutarán ni bloquearán el analizador hasta que el analizador haya terminado de analizar la página y analice y ejecute los scripts en línea que no están marcadosdefer
oasync
.Aquí hay una cita de ese artículo:
La parte relevante de la especificación HTML5 (para navegadores compatibles más nuevos) está aquí . Hay mucho escrito allí sobre el comportamiento asíncrono. Obviamente, esta especificación no se aplica a los navegadores más antiguos (o navegadores mal conformes) cuyo comportamiento probablemente tendría que probar para determinar.
Una cita de la especificación HTML5:
¿Qué pasa con los scripts del módulo Javascript
type="module"
?Javascript ahora tiene soporte para cargar módulos con una sintaxis como esta:
O, con
src
atributo:Todos los scripts con
type="module"
reciben automáticamente eldefer
atributo. Esto los descarga en paralelo (si no en línea) con otra carga de la página y luego los ejecuta en orden, pero después de que se realiza el analizador.Los scripts del módulo también pueden recibir el
async
atributo que ejecutará los scripts del módulo en línea tan pronto como sea posible, sin esperar hasta que se complete el analizador y sin esperar a ejecutar elasync
script en un orden particular en relación con otros scripts.Hay un gráfico de línea de tiempo bastante útil que muestra la búsqueda y ejecución de diferentes combinaciones de scripts, incluidos los scripts de módulo aquí en este artículo: Carga del módulo Javascript .
fuente
defer
le da al analizador la oportunidad de comenzar su descarga antes mientras pospone su ejecución. Tenga en cuenta que si tiene muchas secuencias de comandos del mismo host, comenzar la descarga más pronto en realidad puede ralentizar la descarga de otras personas desde el mismo host (ya que compiten por el ancho de banda) que su página está esperando (eso no es asídefer
) Esto podría ser una espada de doble filo.El navegador ejecutará los scripts en el orden en que los encuentra. Si llama a un script externo, bloqueará la página hasta que el script se haya cargado y ejecutado.
Para probar este hecho:
Las secuencias de comandos agregadas dinámicamente se ejecutan tan pronto como se agregan al documento.
Para probar este hecho:
El orden de las alertas se "agrega" -> "¡hola!" -> "final"
Si en un script intenta acceder a un elemento que aún no se ha alcanzado (ejemplo
<script>do something with #blah</script><div id="blah"></div>
:), recibirá un error.En general, sí, puede incluir scripts externos y luego acceder a sus funciones y variables, pero solo si sale de la
<script>
etiqueta actual y comienza una nueva.fuente
Un gran resumen de @addyosmani
Copiado descaradamente de https://addyosmani.com/blog/script-priorities/
fuente
Después de probar muchas opciones, descubrí que la siguiente solución simple es cargar los scripts cargados dinámicamente en el orden en que se agregan en todos los navegadores modernos
fuente