Retour au blog Performance Web - 5 min

JavaScript bloquant le rendu : defer, async, et le head

Un script sans defer ni async arrête l’analyse du HTML. Quand utiliser defer ou async, et quoi laisser dans le head avec le CSS.

Un script classique dans le head, sans attribut, bloque le navigateur : il arrête de lire le HTML, télécharge le fichier, l’exécute, puis seulement reprend la page. Tant que cette pause dure, le contenu situé plus bas n’est pas affiché. C’est un sujet de performance. La question de savoir ce que Googlebot exécute pour indexer la page est différente : elle est traitée dans JavaScript et le rendu Googlebot.

Le symptôme côté visiteur est un premier affichage tardif, alors que le fichier HTML lui-même est petit. L’enregistrement réseau montre une barre « script » qui retient les lignes suivantes.

Ce que font defer et async

Les deux attributs laissent le téléchargement se faire en parallèle de la lecture du HTML. Ils ne font pas la même chose ensuite.

AttributTéléchargementExécutionOrdre entre scripts
AucunBloque l’analyseImmédiatement, avant la suite du HTMLL’ordre du document, au prix du blocage
deferEn parallèleAprès l’analyse du document, avant DOMContentLoadedConservé
asyncEn parallèleDès que le fichier est prêt, quitte à couper l’analyseNon garanti
type="module"En parallèleComme defer, sauf si async est aussi présentConservé entre modules defer

defer est le bon défaut pour le JavaScript de votre site : il attend que le HTML soit lu, et script-a puis script-b restent dans cet ordre. async convient à un fichier autonome, qui ne doit pas attendre les autres et que les autres n’attendent pas. Deux fichiers async qui se supposent l’un l’autre cassent de façon intermittente, selon celui qui arrive le premier.

Un script en bas de body sans defer bloque moins le début du HTML que le même script dans le head, parce que le navigateur a déjà lu presque tout le document. defer dans le head est en général plus clair : le téléchargement commence tôt, l’exécution attend la fin de l’analyse, et le HTML n’est pas retenu.

CSS et JavaScript dans le head

Le head doit contenir le CSS nécessaire au premier écran. Sans lui, le visiteur voit un flash de contenu non mis en forme, ou rien du tout : le navigateur retient le rendu le temps de lire les feuilles. Gardez cette feuille courte. Le CSS qui ne sert qu’en bas de page ou sur une autre page n’a pas à retarder tout le site. Le détail est dans le guide sur le CSS bloquant.

Le JavaScript n’a presque jamais besoin du même traitement. Dans le head, mettez :

  • la feuille CSS du premier écran ;
  • les scripts en defer (votre code) ou async (un tiers indépendant) ;
  • un préchargement ponctuel si une ressource du premier écran est découverte trop tard, comme expliqué dans le préchargement des ressources.

Ne mettez pas dans le head un script synchrone « parce qu’il a toujours été là », ni une dizaine de fichiers les uns derrière les autres sans attribut. Chaque fichier synchrone ajoute une pause. Les regrouper en un seul fichier synchrone réduit les allers-retours mais ne supprime pas le blocage : le navigateur exécute encore tout avant de continuer le HTML.

Les scripts insérés par un gestionnaire de balises échappent à cette relecture du thème. Un HTML personnalisé peut réintroduire un script bloquant. Il se traite dans le conteneur, pas seulement dans le code source du modèle.

Ordre de correction

  1. Affichez le code source et listez les <script> du head sans defer, sans async et sans type="module".
  2. Pour chacun : s’il dépend du DOM ou d’un autre script du site, ajoutez defer. S’il est isolé, async peut suffire. S’il n’est plus appelé, retirez-le.
  3. Vérifiez dans la console qu’aucune fonction n’est appelée avant le chargement de sa bibliothèque. Une erreur undefined après l’ajout de defer veut dire qu’un petit script inline, plus haut, supposait la bibliothèque déjà exécutée. Passez ce script inline après, ou en defer lui aussi (un inline ne se diffère pas : il faut un fichier, ou le placer en fin de document).
  4. Gardez le CSS du premier écran dans le head, et sortez le reste du chemin critique.
  5. Mesurez le premier affichage avant et après. Si le premier texte arrive plus tôt, le blocage a reculé.

Ne différez pas un script qui doit exister avant le premier pixel pour une raison réelle, par exemple un bandeau qui réserve sa place et dont le décalage visuel serait pire que l’attente. Ces exceptions sont rares. Tout le reste peut attendre la fin de l’analyse du HTML.

Questions fréquentes

Quelle est la différence entre defer et async ?

defer télécharge le script pendant l’analyse du HTML et l’exécute après, en gardant l’ordre des scripts defer. async l’exécute dès qu’il est téléchargé, sans garantir l’ordre, et peut interrompre l’analyse.

Faut-il mettre tous les scripts en async ?

Non. async convient à un script indépendant, comme une mesure d’audience. Un script qui dépend d’un autre, ou qui doit toucher le DOM complet, se met en defer pour garder l’ordre et attendre la fin de l’analyse.

Le CSS dans le head bloque-t-il aussi l’affichage ?

Oui. Une feuille de style dans le head retarde le premier rendu le temps d’être lue. Elle doit rester dans le head pour que le premier écran soit correct, mais elle doit rester courte. Le JavaScript, lui, n’a en général pas besoin de bloquer ce rendu.

Surveiller mes URL