Un script JavaScript placé sans précaution dans une page peut, à lui seul, retarder tout l’affichage de plusieurs centaines de millisecondes. Par défaut, le navigateur interrompt en effet la construction de la page pour télécharger et exécuter chaque script rencontré. Deux attributs permettent d’éviter ce blocage : defer et async. Tous deux autorisent le téléchargement du script en parallèle, mais ils diffèrent sur le moment de l’exécution et sur le respect de l’ordre. Bien les choisir change radicalement la vitesse d’affichage d’un site. Voyons ce que recouvrent ces deux attributs, comment ils modifient le chargement des scripts, en quoi ils améliorent la performance, et comment trancher entre les deux selon la nature du script.
defer et async, définition de deux attributs de chargement
Les attributs defer et async se placent sur la balise qui charge un script et indiquent au navigateur de le télécharger sans interrompre l’analyse de la page. Ils s’inscrivent dans l’optimisation du chemin de rendu critique, en supprimant l’un de ses principaux freins. Tous deux rendent le script non bloquant pour l’affichage, mais selon des modalités différentes qu’il faut bien distinguer.
Le problème des scripts bloquants
Par défaut, quand le navigateur rencontre une balise de script en cours d’analyse, il s’arrête : il télécharge le fichier, l’exécute, puis seulement reprend la construction de la page. Ce comportement prudent évite des incohérences, mais il fige l’affichage le temps du script, d’autant plus longtemps que le fichier est volumineux ou hébergé ailleurs. Le résultat est un écran qui tarde à se remplir, alors même que le contenu textuel serait prêt. Un seul gros script placé en tête de page suffit à repousser le premier affichage de façon très perceptible. Ce blocage du rendu par le JavaScript est l’un des problèmes de performance les plus fréquents sur le web. Historiquement, on contournait ce défaut en plaçant les scripts tout en bas du document, juste avant sa fermeture. La technique fonctionne, mais reste rudimentaire et peu souple. Les attributs defer et async offrent une solution plus fine et explicite, intégrée directement dans la balise, sans dépendre de la position du script dans la page.
Ce que changent defer et async
Le point commun des deux attributs est de permettre le téléchargement du script en parallèle de l’analyse de la page. Le navigateur n’attend plus le fichier pour continuer à construire l’affichage, ce qui supprime le blocage du rendu. C’est déjà, en soi, un gain majeur par rapport au comportement par défaut d’un script classique. Leur différence porte sur le moment de l’exécution. Avec defer, le script attend que la page soit entièrement analysée avant de s’exécuter, dans l’ordre où il apparaît. Avec async, il s’exécute dès qu’il est téléchargé, sans attendre ni garantir d’ordre. Cette divergence sur l’exécution est précisément ce qui guide le choix entre les deux. Comprendre cette distinction est essentiel, car appliquer le mauvais attribut peut introduire des bugs subtils. Un script qui dépend d’un autre supporte mal une exécution dans le désordre. Saisir ce que chacun garantit, et ne garantit pas, permet de choisir en connaissance de cause plutôt que d’appliquer un attribut au hasard en espérant un gain.

Comment defer et async modifient le chargement des scripts
Pour bien choisir, il faut visualiser précisément ce que font defer et async dans la chronologie du chargement. Leurs comportements se ressemblent au téléchargement mais divergent nettement au moment de l’exécution. Ce sujet complète notre précédent article : ressources bloquant le rendu.
Le comportement de defer
Avec l’attribut defer, le script se télécharge en arrière-plan pendant que la page s’analyse, mais son exécution est repoussée jusqu’à ce que toute la page soit prête. Plusieurs scripts en defer s’exécutent ensuite dans leur ordre d’apparition, ce qui préserve les dépendances entre eux. C’est un comportement à la fois non bloquant et prévisible. Cette garantie d’ordre est la grande force de defer. Un script applicatif qui s’appuie sur une bibliothèque chargée avant lui continuera de fonctionner correctement, car la séquence est respectée. On bénéficie ainsi du gain de performance sans sacrifier la cohérence d’exécution, ce qui en fait l’attribut le plus sûr dans la majorité des cas. Le moment d’exécution, juste après l’analyse de la page, convient parfaitement au code qui manipule le contenu. Le script trouve une page complète et stable sur laquelle agir, sans risque d’intervenir trop tôt. Cette synchronisation avec la page prête évite toute une classe d’erreurs liées à des éléments pas encore présents au moment de l’exécution.
Le comportement de async
Avec l’attribut async, le script se télécharge également en parallèle, mais il s’exécute dès qu’il est disponible, sans attendre la fin de l’analyse de la page. Plusieurs scripts en async s’exécutent donc dans un ordre imprévisible, au gré de leur vitesse de téléchargement, sans aucune garantie de séquence entre eux. Cette indépendance fait la force et la faiblesse de l’attribut. Elle est idéale pour des scripts autonomes qui n’ont besoin de rien d’autre, comme un outil de mesure d’audience. Mais elle devient dangereuse dès qu’un script en dépend d’un autre, car l’absence d’ordre garanti peut provoquer des erreurs difficiles à reproduire et à diagnostiquer. Le tableau ci-dessous compare le comportement des deux attributs.
| Attribut | Téléchargement | Exécution |
|---|---|---|
| aucun (défaut) | Bloque l’analyse | Immédiate, bloque le rendu |
| defer | En parallèle | Après l’analyse, dans l’ordre |
| async | En parallèle | Dès que prêt, sans ordre garanti |
Le cas des scripts en ligne et des modules
Ces attributs ne s’appliquent qu’aux scripts externes, ceux chargés depuis un fichier. Un script écrit directement dans la page ne tient pas compte de defer ni d’async, et reste bloquant. Pour profiter de ces optimisations, il faut donc externaliser le code en ligne, ce qui constitue d’ailleurs une bonne pratique pour d’autres raisons de sécurité. Les modules JavaScript, eux, adoptent par défaut un comportement différé proche de defer, sans qu’on ait à le préciser. Cette particularité simplifie le chargement du code moderne, qui est non bloquant d’emblée. Connaître cette nuance évite d’ajouter des attributs inutiles ou d’attendre d’un module un comportement qu’il a déjà nativement. Ces subtilités rappellent qu’un même réglage ne s’applique pas uniformément. Selon que le script est externe, en ligne ou modulaire, son comportement par défaut diffère. Garder cette distinction en tête évite bien des confusions lorsqu’un script ne se comporte pas comme attendu malgré la présence, ou l’absence, d’un attribut de chargement.
Pourquoi defer et async améliorent la performance
Employer defer et async à bon escient agit directement sur la vitesse d’affichage, l’un des piliers mesurés par les Core Web Vitals. En cessant de bloquer le rendu pour chaque script, on rapproche le contenu de l’instant du clic, ce qui améliore nettement la performance perçue sans toucher à la logique du site.
Débloquer le premier affichage
Le gain principal est la levée du blocage au rendu. Tant qu’un script classique se télécharge et s’exécute, la page reste figée ; avec defer ou async, elle continue de se construire. Le premier contenu apparaît donc bien plus tôt, ce qui se mesure directement dans les indicateurs de vitesse d’affichage les plus suivis. Cet effet est particulièrement sensible sur mobile, où la puissance et la connexion sont plus limitées. Un script bloquant y pèse davantage, et le débloquer y change davantage l’expérience. Soigner le chargement des scripts, c’est agir là où la performance est la plus fragile, auprès d’une audience souvent majoritaire et exigeante en réactivité. Le bénéfice s’étend au-delà du premier affichage. En libérant le fil principal plus tôt, on permet aussi à la page de devenir interactive plus rapidement. L’internaute peut agir sans attendre la fin de tous les scripts, ce qui réduit la sensation d’attente et les frustrations liées à une page visible mais qui ne répond pas encore.
Préserver l’ordre quand il le faut
La performance ne doit jamais se payer au prix de bugs. C’est là que defer montre sa valeur : il accélère sans rompre les dépendances, en garantissant l’ordre d’exécution. On obtient ainsi un gain de vitesse sans risque pour la cohérence du code, ce qui en fait le choix par défaut pour le code applicatif structurant. Ignorer cette question de l’ordre expose à des pannes intermittentes, parmi les plus pénibles à diagnostiquer. Un script qui fonctionne un jour et échoue le lendemain, selon la vitesse du réseau, trahit souvent un mauvais usage d’async. Respecter les dépendances évite ces bugs aléatoires, qui coûtent bien plus cher que le temps gagné au chargement. L’enjeu est donc d’optimiser sans déstabiliser. Une stratégie de chargement réussie combine vitesse et fiabilité, en réservant chaque attribut au type de script qui lui convient. Cet équilibre entre rapidité et robustesse distingue une optimisation durable d’un réglage hâtif qui accélère l’affichage tout en semant des dysfonctionnements discrets.

Choisir entre defer et async selon le script
Choisir entre defer et async n’est pas affaire de préférence mais de nature du script. Une règle simple, fondée sur les dépendances et le rôle du code, permet de trancher sans hésitation dans la grande majorité des situations.
defer pour le code de l’application
Pour tout script qui manipule le contenu de la page ou dépend d’un autre, defer est le choix indiqué. Il garantit l’exécution après l’analyse complète et dans l’ordre, ce qui correspond exactement aux besoins du code applicatif. C’est la valeur sûre pour le coeur fonctionnel d’un site, celui dont la cohérence ne peut pas être laissée au hasard. Ce choix vaut aussi pour les bibliothèques dont d’autres scripts dépendent. En les chargeant en defer, on s’assure qu’elles seront prêtes et exécutées avant le code qui s’appuie sur elles. On préserve ainsi la chaîne des dépendances tout en profitant du gain de performance, sans avoir à orchestrer manuellement l’ordre de chargement. En pratique, faire de defer l’attribut par défaut de la plupart des scripts est une stratégie saine. On n’y déroge que pour des cas précis qui justifient l’autre comportement. Cette règle simple par défaut évite de réfléchir à chaque script et écarte la majorité des erreurs liées à un mauvais choix d’attribut.
async pour les scripts indépendants
L’attribut async convient aux scripts totalement autonomes, qui n’ont besoin de rien d’autre et dont personne ne dépend. Les outils de mesure d’audience en sont l’exemple type : ils s’exécutent dans leur coin, sans interagir avec le reste. Pour ce code parfaitement isolé, async offre le chargement le plus précoce possible, sans inconvénient. L’avantage est que ces scripts s’exécutent au plus tôt, dès leur arrivée, sans attendre la fin de l’analyse de la page. Pour un outil de suivi, capter l’information le plus vite possible peut même être souhaitable. L’absence d’ordre garanti n’a ici aucune importance, puisque le script ne s’inscrit dans aucune séquence avec d’autres. Le danger serait d’employer async par habitude pour des scripts dépendants. Réserver cet attribut aux seuls scripts réellement indépendants évite les bugs d’ordre. Garder à l’esprit cette frontière entre code isolé et code lié est la clé d’un usage sûr, qui tire le meilleur de chaque attribut sans en subir les pièges.
Aller plus loin avec le chargement différé
Pour les scripts vraiment secondaires, on peut dépasser defer et async en retardant carrément leur chargement jusqu’à une interaction de l’utilisateur. Un widget de discussion ou un bouton de partage n’a aucune raison de se charger au démarrage. Ce chargement à la demande libère encore davantage les premiers instants de la visite. Cette approche pousse à l’extrême la logique des deux attributs : ne charger que l’essentiel d’abord, le reste ensuite. Elle demande un peu plus de travail, mais offre un gain notable sur les pages encombrées de fonctionnalités accessoires. On concentre alors les ressources sur ce qui compte, c’est-à-dire afficher vite le contenu attendu. Le tableau ci-dessous résume la règle de choix entre les différentes stratégies de chargement.
| Type de script | Stratégie conseillée |
|---|---|
| Code applicatif, dépendances | defer (ordre garanti) |
| Bibliothèque dont d’autres dépendent | defer (prête avant le reste) |
| Outil de mesure autonome | async (exécution au plus tôt) |
| Fonctionnalité accessoire | Chargement différé à l’interaction |

0 commentaires