Passer au contenu principal

Comprendre les attributs defer et async en JavaScript

Lorsque le navigateur charge une page HTML et rencontre une balise <script>, par défaut, il doit interrompre la construction du DOM pour télécharger et exécuter immédiatement ce script. Cette interruption entraîne deux inconvénients majeurs :

  1. Blocage du rendu : Si un script volumineux est placé en haut de la page, il bloque le rendu du contenu. Cela signifie que les utilisateurs ne peuvent pas voir la page tant que le script n'a pas été entièrement téléchargé et exécuté.

  2. Accès limité au DOM : Les scripts insérés avant que le DOM ne soit entièrement construit ne peuvent pas interagir avec les éléments HTML situés après eux dans le code. Par exemple, un script ne pourra pas ajouter de gestionnaires d'événements à des éléments encore non créés dans le DOM.

Pour résoudre ces problèmes, HTML5 introduit deux attributs pour les balises <script> : defer et async. Ces attributs modifient le comportement par défaut du chargement des scripts, permettant d'optimiser la performance de la page.

L'attribut defer

L'attribut defer indique au navigateur de ne pas bloquer la construction du DOM lors du téléchargement du script. Au lieu de cela, le script est chargé en parallèle en arrière-plan pendant que le navigateur continue de construire le DOM. Une fois le DOM entièrement construit, le script est exécuté, juste avant que l'événement DOMContentLoaded ne soit déclenché.

Caractéristiques des scripts avec defer 

  • Pas de blocage : Les scripts marqués avec defer ne bloquent jamais le rendu de la page. Le contenu de la page peut être affiché immédiatement pendant que les scripts sont téléchargés.
  • Exécution ordonnée : L'ordre d'exécution des scripts avec defer est garanti. Même si plusieurs scripts defer sont téléchargés simultanément, ils s'exécuteront dans l'ordre où ils apparaissent dans le document.
  • Exécution après le DOM complet : Les scripts defer s'exécutent après que le DOM est entièrement construit, mais avant que l'événement DOMContentLoaded soit déclenché. Cela signifie que les scripts peuvent interagir avec tous les éléments du DOM.

Quand utiliser l’attribut defer ?

L'attribut defer est particulièrement utile dans les situations suivantes :

  • Exécution après le chargement du DOM : Il permet d'exécuter votre script uniquement après que le DOM est complètement prêt, mais avant le chargement de tous les éléments tels que les images et les styles.

  • Maintien de l'ordre d'exécution : Il garantit que plusieurs scripts s'exécutent dans l'ordre dans lequel ils apparaissent dans le document.

  • Amélioration des performances de chargement : En utilisant defer, le navigateur peut continuer à traiter le HTML et construire le DOM tout en téléchargeant les scripts en parallèle, ce qui contribue à améliorer le temps de chargement de la page.

Exemple d'utilisation de defer

<p>Contenu avant les scripts</p>

<script>
  document.addEventListener('DOMContentLoaded', () => console.log("DOM chargé !"));
</script>

<script src="long.js" defer></script>
<script src="rapide.js" defer></script>

<p>Contenu après les scripts</p>

Voici comment le processus se déroule :

  1. Le navigateur commence par charger et afficher le contenu HTML (le texte avant et après les balises script).

  2. Pendant ce temps, les scripts référencés dans les balises <script src="long.js" defer> et <script src="rapide.js" defer> sont téléchargés en parallèle, mais ne sont pas immédiatement exécutés.

  3. Une fois le DOM complètement chargé, les scripts sont exécutés dans l'ordre d'apparition dans le document, même si long.js prend plus de temps à télécharger que rapide.js. Dans ce cas, long.js s'exécutera avant rapide.js car il apparaît en premier dans le code source.

  4. Après l'exécution des scripts, l'événement DOMContentLoaded est déclenché. Le gestionnaire d'événements associé s'exécute alors, affichant le message "DOM chargé !".

L'attribut async

Les scripts utilisant l'attribut async se chargent en arrière-plan et s'exécutent dès qu'ils sont prêts. Ni le DOM ni les autres scripts n'attendent leur chargement, et ces scripts ne dépendent de rien. Ainsi, un script chargé avec async fonctionne de manière totalement indépendante, s'exécutant dès qu'il est disponible.

Quand utiliser l’attribut async ?

L'attribut async est particulièrement utile dans les situations suivantes :

  • Scripts indépendants : Utilisez async pour des scripts qui ne dépendent pas les uns des autres et n'ont pas besoin d'un ordre d'exécution particulier, comme des scripts de Google Analytics. Cela permet d'optimiser le temps de chargement des scripts.

  • Amélioration des performances : En permettant le chargement parallèle et l'exécution immédiate, async contribue à améliorer les performances de votre page, surtout lorsque des scripts tiers sont impliqués.

Exemple d'utilisation de async

<p>Contenu avant les scripts</p>

<script>
  document.addEventListener('DOMContentLoaded', () => console.log("DOM chargé !"));
</script>

<script src="script_1.js" async></script>
<script src="script_2.js" async></script>

<p>Contenu après les scripts</p>
  1. Le navigateur commence par charger et afficher le contenu HTML, c'est-à-dire le texte avant et après les balises <script>.

  2. Les scripts référencés dans les balises <script src="long.js" async> et <script src="rapide.js" async> sont téléchargés en parallèle, sans attendre que le DOM soit entièrement chargé.

  3. Une fois que chaque script est téléchargé, il est exécuté immédiatement, indépendamment de l'ordre dans lequel ils apparaissent dans le document. Cela signifie que script_2.js peut s'exécuter avant script_1.js si ce dernier prend plus de temps à se charger.

  4. Une fois que le DOM est complètement chargé, l'événement DOMContentLoaded est déclenché. Le gestionnaire d'événements associé s'exécute alors, affichant le message "DOM chargé !".