Si vous ne chargez pas dynamiquement des scripts ou ne les marquez pas comme defer
ou async
, 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 à retenir async
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és defer
dans l'ordre dans lequel ils ont été rencontrés. Cela vous permet de marquer plusieurs scripts qui dépendent les uns des autres comme defer
. 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 pense defer
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és defer
ou async
.
Voici une citation de cet article:
les scripts insérés par script s'exécutent de manière asynchrone dans IE et WebKit, mais de manière synchrone dans Opera et Firefox antérieur à 4.0.
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:
Ensuite, la première des options suivantes qui décrit la situation doit être suivie:
Si l'élément a un attribut src, et l'élément a un attribut defer, et l'élément a été marqué comme "inséré par l'analyseur", et l'élément n'a pas d'attribut async.
L'élément doit être ajouté à la fin de la liste de les scripts qui s'exécuteront une fois l'analyse du document terminée associée au document de l'analyseur qui a créé l'élément.
La tâche que la source de tâches de mise en réseau place dans la file d'attente des tâches une fois l'algorithme d'extraction terminé doit définir l'indicateur "prêt à être exécuté par l'analyseur" de l'élément. L'analyseur gérera l'exécution du script.
Si l'élément a un attribut src et que l'élément a été marqué comme "inséré par l'analyseur" et que l'élément n'a pas d'attribut asynchrone
L'élément est le script de blocage de l'analyse en attente du document de l'analyseur qui a créé l'élément. (Il ne peut y avoir qu'un seul script de ce type par document à la fois.)
La tâche que la source de tâches de mise en réseau place dans la file d'attente des tâches une fois l'algorithme d'extraction terminé doit définir l'indicateur "prêt à être exécuté par l'analyseur" de l'élément. L'analyseur gérera l'exécution du script.
Si l'élément n'a pas d'attribut src et que l'élément a été marqué comme "inséré par l'analyseur" et que le document de l'analyseur HTML ou de l'analyseur XML qui a créé l'élément de script a une feuille de style qui bloque les scripts L'élément est le script de blocage-analyse en attente du document de l'analyseur qui a créé l'élément. (Il ne peut y avoir qu'un seul script de ce type par document à la fois.)
Définissez l'indicateur "prêt à être exécuté par l'analyseur" de l'élément. L'analyseur gérera l'exécution du script.
Si l'élément a un attribut src, n'a pas d'attribut async et n'a pas le flag "force-async" défini L'élément doit être ajouté à la fin de la liste des scripts qui s'exécuteront dans l'ordre dès que possible associés avec le document de l'élément de script au moment de la préparation d'un algorithme de script.
La tâche que la source de tâches de mise en réseau place dans la file d'attente des tâches une fois l'algorithme d'extraction terminé doit exécuter les étapes suivantes:
Si l'élément n'est pas maintenant le premier élément de la liste des scripts qui s'exécutera dans l'ordre dès que possible auquel il a été ajouté ci-dessus, marquez l'élément comme prêt mais abandonnez ces étapes sans exécuter le script pour le moment.
Exécution: Exécutez le bloc de script correspondant au premier élément de script de cette liste de scripts qui s'exécutera dans l'ordre dès que possible.
Supprimez le premier élément de cette liste de scripts qui s'exécutera dans l'ordre dès que possible.
Si cette liste de scripts qui s'exécuteront dans l'ordre dès que possible n'est toujours pas vide et que la première entrée a déjà été marquée comme prête, revenez à l'étape intitulée exécution.
Si l'élément a un attribut src L'élément doit être ajouté à l'ensemble de scripts qui s'exécutera dès que possible du document de l'élément de script au moment du démarrage de la préparation d'un algorithme de script.
La tâche que la source de tâches de mise en réseau place dans la file d'attente des tâches une fois l'algorithme d'extraction terminé doit exécuter le bloc de script, puis supprimer l'élément de l'ensemble de scripts qui s'exécutera dès que possible.
Sinon, l'agent utilisateur doit immédiatement exécuter le bloc de script, même si d'autres scripts sont déjà en cours d'exécution.
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:
<script type="module">
import {addTextToBody} from './utils.mjs';
addTextToBody('Modules are pretty cool.');
</script>
Ou, avec src
attribut:
<script type="module" src="http://somedomain.com/somescript.mjs">
</script>
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 le async
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 .