L'affichage du code HTML avec JavaScript diffère du rendu du code HTML envoyé par le serveur, ce qui peut avoir une incidence sur les performances. Découvrez dans ce guide les différences et ce que vous pouvez faire pour préserver les performances d'affichage de votre site Web, en particulier en ce qui concerne les interactions.
Par défaut, les navigateurs analysent et affichent très bien le code HTML pour les sites Web qui utilisent la logique de navigation intégrée au navigateur (parfois appelée "chargements de page traditionnels"). ou des « navigations difficiles ». Ces sites Web sont parfois appelés applications multipages (MPA).
Toutefois, les développeurs peuvent contourner les paramètres par défaut du navigateur pour répondre aux besoins de leurs applications. C'est certainement le cas des sites Web qui utilisent le modèle SPA (Single Page Application), qui crée de manière dynamique d'importantes parties du code HTML/DOM sur le client à l'aide de JavaScript. Le rendu côté client est le nom qui désigne ce modèle de conception. Il peut avoir des effets sur l'Interaction to Next Paint (INP) de votre site Web si le travail demandé est excessif.
Ce guide vous aide à faire la différence entre l'utilisation du code HTML envoyé par le serveur au navigateur et sa création sur le client avec JavaScript, et la façon dont ce dernier peut générer une latence d'interaction élevée à des moments cruciaux.
Comment le navigateur affiche le code HTML fourni par le serveur
Le modèle de navigation utilisé dans les chargements de page traditionnels implique la réception du code HTML du serveur à chaque navigation. Si vous saisissez une URL dans la barre d'adresse de votre navigateur ou que vous cliquez sur un lien dans une MPA, la série d'événements suivante se produit:
- Le navigateur envoie une requête de navigation pour l'URL fournie.
- Le serveur répond par HTML en fragments.
La dernière étape est essentielle. C'est également l'une des optimisations de performances les plus fondamentales sur l'échange serveur/navigateur. On parle également de flux de données. Si le serveur peut commencer à envoyer du code HTML dès que possible et que le navigateur n'attend pas que l'intégralité de la réponse arrive, le navigateur peut traiter le code HTML en fragments au fur et à mesure de sa réception.
Comme la plupart des choses qui se produisent dans le navigateur, l'analyse du code HTML s'effectue au sein des tâches. Lorsque le code HTML est transmis du serveur au navigateur, celui-ci optimise l'analyse de ce code HTML en le faisant petit à petit, à mesure que des fragments du flux arrivent par morceaux. En conséquence, le navigateur cède périodiquement au thread principal après le traitement de chaque fragment, ce qui évite de longues tâches. Cela signifie que d'autres tâches peuvent être effectuées pendant l'analyse du code HTML, y compris le travail d'affichage incrémentiel nécessaire pour présenter une page à l'utilisateur, ainsi que le traitement des interactions utilisateur qui peuvent se produire pendant la période de démarrage cruciale de la page. Cette approche se traduit par un meilleur score INP (Interaction to Next Paint) pour la page.
Ce qu'il faut retenir ? Lorsque vous diffusez du contenu HTML depuis le serveur, vous bénéficiez d'une analyse et d'un rendu incrémentiels du code HTML, ainsi que d'un rendement automatique et sans frais vers le thread principal. Ce n'est pas le cas avec le rendu côté client.
Comment le navigateur affiche le code HTML fourni par JavaScript
Bien que chaque demande de navigation vers une page nécessite une certaine quantité de HTML devant être fournie par le serveur, certains sites Web utilisent le format SPA. Cette approche implique souvent qu'une charge utile initiale minimale en HTML soit fournie par le serveur, mais le client remplit ensuite la zone de contenu principale d'une page avec du code HTML assemblé à partir des données extraites du serveur. Navigations suivantes (parfois appelées "navigations logicielles") dans ce cas, sont entièrement gérés par JavaScript pour remplir la page avec le nouveau code HTML.
L'affichage côté client peut également se produire dans des applications autres que les applications monopages, dans des cas plus rares où le code HTML est ajouté dynamiquement au DOM via JavaScript.
Il existe plusieurs moyens courants de créer du code HTML ou d'ajouter des éléments au DOM via JavaScript:
- La propriété
innerHTML
vous permet de définir le contenu d'un élément existant via une chaîne, que le navigateur analyse dans le DOM. - La méthode
document.createElement
vous permet de créer des éléments à ajouter au DOM sans analyse HTML du navigateur. - La méthode
document.write
vous permet d'écrire du code HTML dans le document (et le navigateur l'analyse, comme pour l'approche n° 1). Toutefois, pour plusieurs raisons, l'utilisation dedocument.write
est fortement déconseillée.
La création d'éléments HTML/DOM à l'aide de JavaScript côté client peut avoir des conséquences importantes:
- Contrairement au code HTML diffusé par le serveur en réponse à une requête de navigation, les tâches JavaScript sur le client ne sont pas automatiquement fragmentées, ce qui peut entraîner de longues tâches qui bloquent le thread principal. Cela signifie que l'INP de votre page peut être affecté si vous créez trop de code HTML/DOM en même temps sur le client.
- Si le code HTML est créé sur le client au démarrage, les ressources référencées dans celui-ci ne seront pas détectées par l'outil d'analyse du préchargement du navigateur. Cela aura certainement un effet négatif sur la Largest Contentful Paint (LCP) d'une page. Bien qu'il ne s'agisse pas d'un problème de performances d'exécution (mais d'un retard du réseau lors de l'extraction de ressources importantes), vous ne voulez pas que le LCP de votre site Web soit affecté en contournant cette optimisation fondamentale des performances du navigateur.
Que pouvez-vous faire concernant l'impact du rendu côté client sur les performances ?
Si votre site Web dépend beaucoup du rendu côté client et que vous avez constaté des valeurs INP incorrectes dans vos données de champ, vous vous demandez peut-être si le rendu côté client est en lien avec le problème. Par exemple, si votre site Web est une application monopage, vos données de terrain peuvent révéler des interactions responsables d'un travail de rendu considérable.
Quelle que soit la cause du problème, voici quelques causes potentielles à explorer pour vous aider à résoudre le problème.
Fournissez autant de code HTML que possible à partir du serveur.
Comme indiqué précédemment, le navigateur gère par défaut le code HTML du serveur de manière très performante. Il brisera l'analyse et l'affichage du code HTML d'une manière qui évite les longues tâches et optimise la durée totale du thread principal. Cela se traduit par une durée de blocage totale (TBT) plus faible, qui est fortement corrélée à l'INP.
Vous utilisez peut-être un framework d'interface pour créer votre site Web. Si tel est le cas, assurez-vous d'afficher le code HTML des composants sur le serveur. Cela limitera le nombre de rendus initiaux côté client que votre site Web aura besoin, ce qui devrait offrir une meilleure expérience.
- Pour React, vous devez utiliser l'API Server DOM afin d'afficher le code HTML sur le serveur. Sachez toutefois que la méthode traditionnelle d'affichage côté serveur utilise une approche synchrone, ce qui peut entraîner un délai avant le premier octet (TTFB) plus long, ainsi que des métriques ultérieures telles que First Contentful Paint (FCP) et LCP. Dans la mesure du possible, veillez à utiliser les API de streaming pour Node.js ou d'autres environnements d'exécution JavaScript afin que le serveur puisse commencer à diffuser du code HTML dans le navigateur dès que possible. Next.js, un framework basé sur React, propose de nombreuses bonnes pratiques par défaut. En plus d'afficher automatiquement le code HTML sur le serveur, il peut également générer du code HTML de manière statique pour les pages qui ne changent pas en fonction du contexte de l'utilisateur (comme l'authentification).
- Vue effectue également un rendu côté client par défaut. Toutefois, comme React, Vue peut également afficher le code HTML de vos composants sur le serveur. Exploitez ces API côté serveur dans la mesure du possible ou envisagez une abstraction de niveau supérieur pour votre projet Vue afin de faciliter la mise en œuvre des bonnes pratiques.
- Svelte affiche le code HTML sur le serveur par défaut. Toutefois, si le code de votre composant doit avoir accès à des espaces de noms propres au navigateur (
window
, par exemple), vous ne pourrez peut-être pas afficher le code HTML de ce composant sur le serveur. Dans la mesure du possible, essayez d'autres approches afin de ne pas provoquer un affichage côté client inutile. SvelteKit, qui s'appelle Svelte comme Next.js est to React, intègre de nombreuses bonnes pratiques dans vos projets Svelte autant que possible, afin que vous puissiez éviter les pièges potentiels dans les projets qui utilisent Svelte seul.
Limiter le nombre de nœuds DOM créés sur le client
Lorsque les DOM sont volumineux, le traitement requis pour les afficher a tendance à augmenter. Que votre site Web soit une SPA à part entière ou qu'il injecte de nouveaux nœuds dans un DOM existant à la suite d'une interaction pour une approbation multipartite, pensez à réduire au maximum la taille de ces DOM. Cela permettra de réduire la charge de travail nécessaire au rendu côté client pour afficher ce code HTML, ce qui devrait contribuer à réduire l'INP de votre site Web.
Envisagez d'utiliser une architecture Service Worker de streaming
Il s'agit d'une technique avancée, qui peut ne pas fonctionner facilement dans tous les cas d'utilisation, mais elle peut transformer votre MPA en site Web qui donne l'impression qu'il se charge instantanément lorsque les utilisateurs naviguent d'une page à l'autre. Vous pouvez faire appel à un service worker pour mettre en pré-cache les parties statiques de votre site Web dans CacheStorage
tout en utilisant l'API ReadableStream
pour récupérer le reste du code HTML d'une page à partir du serveur.
Lorsque cette technique fonctionne, vous ne créez pas de code HTML sur le client, mais le chargement instantané des parties du contenu à partir du cache donnera l'impression que votre site se charge rapidement. Les sites Web qui utilisent cette approche peuvent presque ressembler à une SPA, mais sans les inconvénients du rendu côté client. De plus, cela réduit la quantité de code HTML que vous demandez au serveur.
Pour résumer, l'architecture d'un service worker de streaming ne remplace pas la logique de navigation intégrée du navigateur, mais elle s'y ajoute. Pour savoir comment y parvenir avec Workbox, consultez Des applications multipages plus rapides grâce aux flux.
Conclusion
La façon dont votre site Web reçoit et affiche le code HTML a un impact sur les performances. Lorsque vous comptez sur le serveur pour envoyer la totalité (ou la majeure partie) du code HTML nécessaire au fonctionnement de votre site Web, vous en obtenez beaucoup sans frais: l'analyse et l'affichage incrémentiels, et le rendement automatique au thread principal pour éviter de longues tâches.
L'affichage HTML côté client introduit un certain nombre de problèmes de performances potentiels qui peuvent être évités dans de nombreux cas. Cependant, en raison des exigences propres à chaque site Web, il n'est pas totalement évitable à chaque fois. Pour limiter les longues tâches qui peuvent être dues à l'affichage excessif de code sur le site du client, veillez à envoyer autant de code HTML de votre site Web à partir du serveur dans la mesure du possible, à des tailles de DOM aussi petites que possible pour le code HTML qui doit être affiché sur le client. Envisagez d'autres architectures pour accélérer la livraison du code HTML au client, tout en tirant parti de l'analyse incrémentielle et de l'affichage fournis par le navigateur pour le code HTML chargé à partir du serveur.
Si vous pouvez obtenir un affichage côté client aussi minimal que possible, vous améliorerez non seulement l'INP de votre site Web, mais aussi d'autres métriques telles que le LCP, le TTFB et même le TTFB dans certains cas.
Image principale tirée de Unsplash, par Maik Jonietz.