Déjà pointée du doigt par les outils historiques d’audit de la performance front-end comme Google Page Speed, l’utilisation de l’instruction document.write pour injecter un script pose des problèmes importants pour le temps de chargement des sites web.
A l’occasion d’une mise à jour de Chrome, qui fait revenir ce sujet dans l’actualité du moment, penchons nous sur les problèmes posés et les alternatives à envisager.
Chrome n’exécute plus le code document.write
La nouvelle est tombée en 2016 sur le site developers.google.com par l’intermédiaire de Paul Kinlan.
Depuis sa version 55, Chrome intervient à l’encontre de l’instruction document.write lorsque les conditions de réseau ne sont pas favorables. Même quand elles le sont, des avertissements sont visibles dans la console développeur si jamais la page est concernée.
Quelle est la nature de ce blocage? Heureusement pour beaucoup de sites, ce blocage est en fait très contextualisé :
l’utilisateur est sur une connexion bas débit,
le script qui est injecté l’est de manière synchrone (absence d’attribut async et defer) et n’est pas en cache sur la navigateur,
l’instruction est appelée sur la page principale (e.g. les iframes ne sont pas concernées)
Si ces conditions sont réunies, le script appelé ne se charge tout simplement pas.On pourrait s’attendre à ce que les choses ait largement évolué depuis 2016 et que très peu de sites soient encore concernés. C’est faux. En 2022, 7 ans plus tard, au moins 20% des pages WordPress (le CMS le plus utilisé sur le Web) exécutent un document.write durant le chargement initial des pages (source: Rick Viscomi, Google).
Attention donc si votre site utilise des services externes, car même si vous n’utilisez pas cette instruction vous même, votre site pourrait avoir une telle dépendance. Si c’est le cas, sachez donc qu’elle ne fonctionne pas pour une partie de vos utilisateurs.
L’approche de Chrome est intéressante car elle contraint les propriétaires de sites web à l’abandon de (très) mauvaises pratiques. Comme nous allons le voir par la suite, l’instruction document.write occasionne en effet des problèmes de performance significatifs.
Les problèmes posés par document.write
Lorsque vous utilisez l’instruction Javascript suivante pour injecter un script :
document.write(”);
vous empêchez le parser du navigateur de continuer son exécution sur le code HTML qui pourrait suivre. Le navigateur web va rester bloqué sur cette instruction jusqu’à ce que le script soit téléchargé, mais aussi exécuté.
Et la situation peut être encore plus défavorable, puisque le navigateur va également rester bloqué si ce même script en injecte d’autres ! Un cas qui n’est pas si rare parmi les services externes que l’on peut être amené à utiliser sur nos pages web.
Chrome a d’ailleurs publié les résultats de ses tests dans son annonce : 7.6 % des pages seraient concernées.
Pour savoir à quel point l’instruction document.write peut nuire à la performance, là encore on peut s’intéresser aux résultats obtenus par les tests de Chrome sur 1 % de ses utilisateurs reposant sur une connexion 2G : un gain de 38 % sur le temps moyen nécessaire pour interpréter une page, ce qui représente près de 6 secondes gagnées !
Un autre problème qui peut se poser par l’utilisation de cette instruction document.write, et pas uniquement pour injecter un script : si la construction de l’arbre DOM a été achevée, l’utiliser implique de le reconstruire complètement, ce qui est une opération coûteuse ! (document.write écrit dans le flux du document, une fois ce flux fermé tout appel a donc pour conséquence une réinitialisation).
Méthode document.write : comment éviter de l’utiliser ?
De manière générale, vous devez éviter d’utiliser du Javascript de manière bloquante. Les attributs defer et async vous permettront d’appeler des scripts externes de manière asynchrone.
Attention cependant à l’ordre d’exécution de vos scripts dans le cas d‘un chargement asynchrone, il n’est pas garanti !
Si c’est un service externe qui est responsable d’un tel appel à document.write, vérifiez que le fournisseur ne propose pas une autre intégration. Envisagez sinon une alternative.
Enfin, pour insérer du contenu sur vos pages, préférez une manipulation du DOM plutôt que l’utilisation de document.write. Voici un exemple d’insertion de script :
var sNew = document.createElement(“script”);
sNew.async = true;
sNew.src = “https://example.com/script.min.js”;
var s0 = document.getElementsByTagName(‘script’)[0];
s0.parentNode.insertBefore(sNew, s0);
Professionnel du web depuis plus de 15 ans, je m’intéresse à l’ensemble des sujets de la Qualité Web, à commencer par la Performance Web. Solution Expert pour Contentsquare, j’accompagne nos clients, des divisions marketing aux département IT, dans l’audit en temps-réel des problématiques techniques intervenant côté client : performance web, erreurs JS et APIS, pertinence des message affichés… afin de soutenir des stratégies d’optimisation de l’acquisition, de le conversion ou réduire le Time-to-Fix.