Scripts : async, defer
Apprenez comment les attributs async et defer de JavaScript contrôlent le chargement des scripts pour optimiser les performances de chargement des pages.
L'emplacement d'un <script> et la façon dont vous le chargez ont un effet direct sur la rapidité avec laquelle votre page devient utilisable. Par défaut, les scripts peuvent bloquer le navigateur en plein rendu ; les attributs async et defer vous permettent d'indiquer au navigateur de télécharger JavaScript en arrière-plan à la place. Cet article explique le comportement des scripts bloquants ordinaires, ce que async et defer modifient, pourquoi les scripts de module sont différés automatiquement, et comment choisir la bonne option pour chaque script.
Comment un script ordinaire bloque l'analyse
Un <script> sans async ni defer est bloquant pour le rendu. Lorsque l'analyseur HTML atteint la balise, il cesse de construire la page, récupère le script (s'il possède un attribut src), l'exécute jusqu'à la fin, puis reprend l'analyse du reste du document :
<p>...content before script...</p>
<script src="big.js"></script> <!-- parsing pauses here until big.js downloads AND runs -->
<p>...content after script (the user can't see this yet)...</p>Deux conséquences en découlent :
- Le script ne peut pas voir les éléments DOM qui apparaissent après lui, car ils n'ont pas encore été analysés.
- L'utilisateur fixe une page partiellement construite pendant le téléchargement du script. Sur un réseau lent, c'est le classique problème de la « page blanche ».
La solution historique consistait à placer les scripts tout en bas du <body>. Les attributs async et defer offrent une solution plus propre : conserver la balise dans le <head> tout en évitant qu'elle bloque.
Les attributs
asyncetdefern'ont d'effet que sur les scripts externes — ils nécessitent l'attributsrc. Ils sont ignorés sur les blocs<script>en ligne.
Comprendre l'attribut async
Qu'est-ce que l'attribut async ?
Lorsque vous ajoutez l'attribut async à une balise <script>, cela indique au navigateur de télécharger le script en arrière-plan sans bloquer l'analyse HTML. Dès que le téléchargement est terminé, le navigateur suspend l'analyse, exécute le script, puis continue. Comme les temps de téléchargement varient, les scripts async s'exécutent dès qu'ils sont prêts — dans un ordre imprévisible, potentiellement avant que le reste du document n'ait été analysé.
Cela rend async parfait pour les scripts indépendants qui ne dépendent ni du DOM ni les uns des autres : analytics, publicités et autres traceurs « fire-and-forget ».
Exemple de code : utilisation de async
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Async Example</title>
</head>
<body>
<h1>Testing Async</h1>
<script async src="https://example.com/async-script.js"></script>
</body>
</html>Avantages et compromis de async
- Non bloquant : l'analyse HTML se poursuit pendant le téléchargement du script.
- S'exécute dès que possible : le script s'exécute au moment où son téléchargement se termine — idéal pour les scripts indépendants.
- Aucun ordre garanti : avec plusieurs scripts
async, celui qui se télécharge en premier s'exécute en premier. N'utilisez jamaisasyncpour des scripts qui dépendent les uns des autres. - Peut s'exécuter avant que le DOM soit prêt : il peut s'exécuter avant la fin de l'analyse, alors ne supposez pas que les éléments ultérieurs existent.
Exploiter l'attribut defer
Qu'est-ce que l'attribut defer ?
L'attribut defer télécharge également le script en arrière-plan sans bloquer l'analyse. La différence réside dans le moment où il s'exécute : un script différé n'est exécuté qu'après que le document HTML a été entièrement analysé, et juste avant que l'événement DOMContentLoaded ne se déclenche. Les scripts différés conservent également leur ordre dans le document — la première balise defer s'exécute toujours avant la seconde, quel que soit celui qui se télécharge en premier.
Cela fait de defer le bon choix par défaut pour votre code d'application : l'ensemble du DOM est garanti d'exister, et les scripts dépendants restent dans l'ordre.
Exemple de code : utilisation de defer
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Defer Example</title>
</head>
<body>
<h1>Testing Defer</h1>
<script defer src="https://example.com/defer-script.js"></script>
</body>
</html>Avantages de l'utilisation de defer
- DOM prêt : l'intégralité du document HTML est analysée avant l'exécution du script.
- Ordre maintenu : les scripts s'exécutent dans l'ordre du document, ce qui est essentiel pour les scripts qui dépendent les uns des autres.
Les scripts de module sont différés par défaut
Un <script type="module"> se comporte automatiquement comme un script différé — vous n'avez pas besoin d'ajouter defer. Il est récupéré sans bloquer l'analyse et s'exécute après l'analyse du document, dans l'ordre. Pour qu'un module s'exécute dès qu'il est prêt (le comportement async), ajoutez async explicitement :
<!-- Deferred automatically; runs after parsing, in order -->
<script type="module" src="app.js"></script>
<!-- Opt into async: runs as soon as it (and its imports) are ready -->
<script type="module" async src="tracker.js"></script>Si vous débutez avec les modules, consultez l'introduction aux modules.
async vs defer en un coup d'œil
| Comportement | async | defer |
|---|---|---|
| Bloque l'analyse HTML ? | Non | Non |
| Quand s'exécute-t-il ? | Dès que le téléchargement est terminé | Après l'analyse, avant DOMContentLoaded |
| Ordre d'exécution | Celui qui se télécharge en premier | Ordre du document, garanti |
| DOM entièrement disponible ? | Non garanti | Oui |
| Idéal pour | Scripts indépendants (analytics, publicités) | Code d'application, scripts dépendants |
Une règle simple :
- Utilisez
asynclorsque le script est autonome — il ne dépend ni d'autres scripts ni du DOM. - Utilisez
deferlorsque le script a besoin de l'ensemble du DOM, ou lorsque l'ordre d'exécution est important.
Exemple pratique : décisions de chargement de scripts
Considérez le chargement d'une bibliothèque utilitaire (comme Lodash) ainsi que votre propre fichier qui en dépend. Comme l'ordre est important ici, defer est le bon choix — les deux se téléchargent en arrière-plan mais s'exécutent en séquence après l'analyse :
<script defer src="https://cdn.jsdelivr.net/npm/lodash/lodash.min.js"></script>
<script defer src="script.js"></script>Ici, lodash.min.js est garanti de s'exécuter avant script.js, et les deux attendent que la page soit analysée. Passer ces scripts en async risquerait que script.js s'exécute en premier et échoue parce que Lodash n'est pas encore chargé.
Pour le chargement de ressources non-script (images, styles) et la réaction à leur succès ou leur échec, consultez Chargement de ressources : onload et onerror.
Conclusion
L'utilisation efficace des attributs async et defer dans les balises script est essentielle au développement web moderne. En comprenant et en appliquant correctement ces attributs, les développeurs peuvent garantir des chargements de page plus rapides et une meilleure expérience utilisateur. Le chargement asynchrone des scripts est une question d'optimisation des performances et de création d'applications web efficaces et centrées sur l'utilisateur.