Il y a tellement de façons différentes d'inclure JavaScript dans une page html. Je connais les options suivantes:
- code en ligne ou chargé à partir de l'URI externe
- inclus dans la balise <head> ou <body> [ 1 , 2 ]
- n'en avoir aucun
defer
ouasync
attribut (uniquement les scripts externes) - inclus dans la source statique ou ajouté dynamiquement par d'autres scripts (à différents états d'analyse, avec différentes méthodes)
Sans compter les onEvent
scripts de navigation du disque dur, javascript: URI et attributs [ 3 ], il existe déjà 16 alternatives pour exécuter JS et je suis sûr d'avoir oublié quelque chose.
Je ne suis pas tellement préoccupé par le chargement rapide (parallèle), je suis plus curieux de l'ordre d'exécution (qui peut dépendre de l'ordre de chargement et de l' ordre des documents ). Existe-t-il une bonne référence (cross-browser) qui couvre vraiment tous les cas? Par exemple, http://www.websiteoptimization.com/speed/tweak/defer/ ne traite que de 6 d'entre eux et teste principalement les anciens navigateurs.
Comme je crains qu'il n'y en ait pas, voici ma question spécifique: j'ai quelques scripts de tête (externes) pour l'initialisation et le chargement de script. Ensuite, j'ai deux scripts statiques en ligne à la fin du corps. Le premier permet au chargeur de script d'ajouter dynamiquement un autre élément de script (référençant des js externes) au corps. Le deuxième des scripts statiques en ligne veut utiliser js à partir du script externe ajouté. Peut-il compter sur l'exécution de l'autre (et pourquoi :-)?
la source
Réponses:
Si vous ne chargez pas dynamiquement des scripts ou ne les marquez pas comme
defer
ouasync
, les scripts sont chargés dans l'ordre rencontré dans la page. Peu importe qu'il s'agisse d'un script externe ou d'un script en ligne - ils sont exécutés dans l'ordre où ils sont rencontrés dans la page. Les scripts en ligne qui viennent après les scripts externes sont conservés jusqu'à ce que tous les scripts externes qui les ont précédés soient chargés et exécutés.Les scripts asynchrones (quelle que soit la façon dont ils sont spécifiés comme asynchrones) se chargent et s'exécutent dans un ordre imprévisible. Le navigateur les charge en parallèle et il est libre de les exécuter dans l'ordre de son choix.
Il n'y a pas d'ordre prévisible entre plusieurs choses asynchrones. Si l'on avait besoin d'un ordre prévisible, il faudrait le coder en s'enregistrant pour les notifications de chargement à partir des scripts asynchrones et en séquençant manuellement les appels javascript lorsque les éléments appropriés sont chargés.
Lorsqu'une balise de script est insérée dynamiquement, le comportement de l'ordre d'exécution dépend du navigateur. Vous pouvez voir comment Firefox se comporte dans cet article de référence . En résumé, les versions les plus récentes de Firefox utilisent par défaut une balise de script ajoutée dynamiquement à async sauf si la balise de script a été définie autrement.
Une balise de script avec
async
peut être exécutée dès qu'elle est chargée. En fait, le navigateur peut suspendre l'analyseur de tout ce qu'il faisait et exécuter ce script. Donc, il peut vraiment fonctionner à presque n'importe quel moment. Si le script a été mis en cache, il peut s'exécuter presque immédiatement. Si le script prend un certain temps à charger, il peut s'exécuter une fois l'analyseur terminé. La seule chose à retenirasync
est qu'il peut s'exécuter à tout moment et que l'heure n'est pas prévisible.Une balise de script
defer
attend jusqu'à ce que l'analyseur complet soit terminé, puis exécute tous les scripts marquésdefer
dans l'ordre dans lequel ils ont été rencontrés. Cela vous permet de marquer plusieurs scripts qui dépendent les uns des autres commedefer
. Ils seront tous reportés jusqu'à ce que l'analyseur de document soit terminé, mais ils s'exécuteront dans l'ordre où ils ont été rencontrés, tout en préservant leurs dépendances. Je pensedefer
que les scripts sont déposés dans une file d'attente qui sera traitée une fois l'analyseur terminé. Techniquement, le navigateur peut télécharger les scripts en arrière-plan à tout moment, mais ils n'exécuteront ni ne bloqueront l'analyseur tant que l'analyseur n'aura pas terminé l'analyse de la page et l'analyse et l'exécution de scripts en ligne non marquésdefer
ouasync
.Voici une citation de cet article:
La partie pertinente de la spécification HTML5 (pour les navigateurs compatibles plus récents) est ici . Il y a beaucoup écrit là-dessus sur le comportement asynchrone. Évidemment, cette spécification ne s'applique pas aux navigateurs plus anciens (ou aux navigateurs mal conformes) dont vous auriez probablement à tester le comportement pour déterminer.
Une citation de la spécification HTML5:
Qu'en est-il des scripts de module Javascript
type="module"
?Javascript prend désormais en charge le chargement de modules avec une syntaxe comme celle-ci:
Ou, avec
src
attribut:Tous les scripts avec
type="module"
reçoivent automatiquement l'defer
attribut. Cela les télécharge en parallèle (sinon en ligne) avec un autre chargement de la page, puis les exécute dans l'ordre, mais une fois l'analyseur terminé.Les scripts de module peuvent également recevoir l'
async
attribut qui exécutera les scripts de module en ligne dès que possible, sans attendre la fin de l'analyseur et sans attendre d'exécuter leasync
script dans un ordre particulier par rapport aux autres scripts.Il y a un graphique chronologique assez utile qui montre la récupération et l'exécution de différentes combinaisons de scripts, y compris les scripts de module ici dans cet article: Chargement du module Javascript .
la source
defer
donne à l'analyseur la possibilité de commencer son téléchargement plus tôt tout en différant son exécution. Notez que si vous avez beaucoup de scripts du même hôte, alors le démarrage du téléchargement plus tôt peut en fait ralentir le téléchargement des autres depuis le même hôte (car ils rivalisent pour la bande passante) que votre page attend (qui ne le sont pasdefer
) donc cela pourrait être une épée à double tranchant.Le navigateur exécutera les scripts dans l'ordre où ils les trouveront. Si vous appelez un script externe, il bloquera la page jusqu'à ce que le script soit chargé et exécuté.
Pour tester ce fait:
Les scripts ajoutés dynamiquement sont exécutés dès qu'ils sont ajoutés au document.
Pour tester ce fait:
L'ordre des alertes est "ajouté" -> "bonjour!" -> "final"
Si dans un script vous tentez d'accéder à un élément qui n'a pas encore été atteint (exemple
<script>do something with #blah</script><div id="blah"></div>
:), vous obtiendrez une erreur.Dans l'ensemble, oui, vous pouvez inclure des scripts externes, puis accéder à leurs fonctions et variables, mais uniquement si vous quittez la
<script>
balise actuelle et en commencez une nouvelle.la source
Un excellent résumé par @addyosmani
Copie sans vergogne de https://addyosmani.com/blog/script-priorities/
la source
Après avoir testé de nombreuses options, j'ai constaté que la solution simple suivante charge les scripts chargés dynamiquement dans l'ordre dans lequel ils sont ajoutés dans tous les navigateurs modernes
la source