À propos de ce cours
Comprenez comment le navigateur charge les scripts et pourquoi un script classique bloque l'affichage de la page. Cette leçon compare les attributs async et defer et les modules, présente les événements DOMContentLoaded et load, et montre avec un exemple comment observer l'ordre d'exécution des scripts dans la console et l'onglet Réseau. Avec des activités pour choisir le bon attribut.
-
Objectifs
- Comprendre pourquoi un script classique bloque l'affichage de la page.
- Connaître le fonctionnement des attributs
asyncetdefer. - Choisir le bon attribut selon le type de script.
- Utiliser les événements
DOMContentLoadedetload.
-
Le problème : le script qui bloque la page
- Le navigateur construit la page en analysant le HTML de haut en bas (on parle de parsing).
- Quand il rencontre un
<script src="...">classique, il met l'analyse en pause, télécharge le fichier, l'exécute, puis reprend la lecture du HTML. - Conséquences : sur une connexion lente ou avec un gros fichier, la page reste blanche ; et le script ne peut pas accéder aux éléments placés après lui.

-
L'attribut async
<script src="js/statistiques.js" async></script>
- Le fichier est téléchargé en parallèle, sans bloquer l'analyse du HTML.
- Il est exécuté dès qu'il est prêt, ce qui interrompt alors brièvement l'analyse.
- L'ordre d'exécution n'est pas garanti: le fichier le plus rapide à télécharger s'exécute en premier.
- Le DOM peut ne pas être complet au moment de l'exécution.
- À réserver aux scripts indépendants qui ne touchent pas à la page et ne dépendent d'aucun autre script : statistiques de visite, publicité, widgets externes.
L'attribut defer
<script src="js/outils.js" defer></script>
<script src="js/app.js" defer></script>
- Le fichier est téléchargé en parallèle, sans bloquer l'analyse du HTML.
- Il est exécuté une fois l'analyse terminée: tous les éléments de la page existent.
- Les scripts
defers'exécutent dans l'ordre où ils apparaissent :outils.jsavantapp.js. - Ils s'exécutent avant l'événement
DOMContentLoaded. - C'est le choix recommandé pour le code de votre application.
Comparaison
<script> | async | defer | type="module" | |
|---|---|---|---|---|
| Bloque l'analyse du HTML pendant le téléchargement | Oui | Non | Non | Non |
| Moment de l'exécution | Immédiatement | Dès que téléchargé | Après l'analyse du HTML | Après l'analyse du HTML |
| Ordre respecté entre plusieurs scripts | Oui | Non | Oui | Oui |
| DOM complet à l'exécution | Seulement pour ce qui précède | Pas garanti | Oui | Oui |
| Usage typique | Ancien code | Statistiques, publicité | Code de l'application | Code moderne avec import |
Bon à savoir :
async et defer ne concernent que les scripts externes (avec src) ; ils sont ignorés sur un script interne classique. Les modules (type="module") sont différés par défaut ; on peut leur ajouter async. -
Les événements DOMContentLoaded et load
DOMContentLoadedest déclenché surdocumentquand le HTML est entièrement analysé et que les scriptsdeferont été exécutés (sans attendre les images).loadest déclenché surwindowquand tout est chargé : images, feuilles de style, iframes.- Avant l'arrivée de
defer, on entourait le code deDOMContentLoadedpour attendre la page. Avecdefer, ce n'est plus nécessaire, mais vous le rencontrerez souvent dans du code existant.
document.addEventListener("DOMContentLoaded", () => { console.log("Le HTML est prêt : je peux manipuler le DOM"); }); window.addEventListener("load", () => { console.log("Toutes les images sont chargées"); }); -
Exemple : observer l'ordre d'exécution
- Créez trois fichiers qui affichent leur nom dans la console, puis la page :
// js/a.js console.log("a.js exécuté"); // js/b.js console.log("b.js exécuté"); // js/c.js console.log("c.js exécuté, titre :", document.querySelector("h1")?.textContent);<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <title>Ordre des scripts</title> <script src="js/a.js" async></script> <script src="js/b.js" defer></script> <script src="js/c.js" defer></script> <script> document.addEventListener("DOMContentLoaded", () => console.log("DOMContentLoaded")); window.addEventListener("load", () => console.log("load")); </script> </head> <body> <h1>Ordre de chargement</h1> <img src="https://picsum.photos/800/400" alt="Image de test"> </body> </html>- Résultat habituel :
b.jspuisc.js(qui trouve bien le titre), puisDOMContentLoaded, et enfinloadaprès l'image. La position dea.js(async) peut varier d'un rechargement à l'autre. - Dans l'onglet Réseau des DevTools, activez la limitation (Slow 4G) et rechargez : observez la cascade de téléchargement.
-
Activités
Activité 1 : prédire l'ordre
- Avant d'exécuter l'exemple, écrivez l'ordre d'affichage que vous attendez. Exécutez-le cinq fois avec Live Server : l'ordre change-t-il ? Pour quel script ?
Activité 2 : choisir le bon attribut
- Pour chaque script, choisissez entre aucun attribut,
async,deferoutype="module", et justifiez :- le fichier
app.jsqui ajoute des événements aux boutons de la page ; - le script de mesure d'audience fourni par un service externe ;
bootstrap.bundle.min.js, utilisé ensuite parapp.js;main.js, qui contient des instructionsimport.
- le fichier
Activité 3 : le piège de async
- Remplacez
deferparasyncsurb.jsetc.js, puis faites dépendrec.jsd'une fonction déclarée dansb.js. Rechargez plusieurs fois avec la limitation réseau : que se passe-t-il parfois ? Expliquez. - Déposez vos fichiers et vos observations dans le dépôt GitHub
js-defer-async.
Corrigé de l'activité 2. 1 :
Activité 3 : avec
defer (besoin du DOM complet). 2 : async (indépendant de la page et des autres scripts). 3 : defer, placé avant app.js pour garder l'ordre. 4 : type="module" (différé automatiquement).Activité 3 : avec
async, c.js peut s'exécuter avant b.js: la fonction n'existe pas encore et la console affiche une ReferenceError. À retenir
- Un script classique bloque l'analyse de la page.
async: téléchargement parallèle, exécution dès que prêt, ordre non garanti.defer: téléchargement parallèle, exécution après l'analyse du HTML, dans l'ordre. C'est le choix par défaut pour votre code.- Les modules sont différés automatiquement ;
DOMContentLoadedsignale que le HTML est prêt,loadque tout est chargé.
Sources : MDN Web Docs (developer.mozilla.org), documentation de Visual Studio Code et des Chrome DevTools.