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.
| Attribut | Téléchargement | Exécution | Ordre entre scripts |
|---|---|---|---|
| Aucun | Bloque l’analyse | Immédiatement, avant la suite du HTML | L’ordre du document, au prix du blocage |
defer | En parallèle | Après l’analyse du document, avant DOMContentLoaded | Conservé |
async | En parallèle | Dès que le fichier est prêt, quitte à couper l’analyse | Non garanti |
type="module" | En parallèle | Comme defer, sauf si async est aussi présent | Conservé 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) ouasync(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
- Affichez le code source et listez les
<script>duheadsansdefer, sansasyncet sanstype="module". - Pour chacun : s’il dépend du DOM ou d’un autre script du site, ajoutez
defer. S’il est isolé,asyncpeut suffire. S’il n’est plus appelé, retirez-le. - Vérifiez dans la console qu’aucune fonction n’est appelée avant le chargement de sa bibliothèque. Une erreur
undefinedaprès l’ajout dedeferveut dire qu’un petit script inline, plus haut, supposait la bibliothèque déjà exécutée. Passez ce script inline après, ou endeferlui aussi (un inline ne se diffère pas : il faut un fichier, ou le placer en fin de document). - Gardez le CSS du premier écran dans le
head, et sortez le reste du chemin critique. - 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.
