L'affichage du code HTML avec JavaScript diffère du rendu HTML envoyé par le serveur, et cela peut affecter les performances. Découvrez les différences présentées dans ce guide et comment préserver les performances d'affichage de votre site Web, en particulier en ce qui concerne les interactions.
Par défaut, les navigateurs font très bien l'analyse et l'affichage du code HTML pour les sites Web qui utilisent la logique de navigation intégrée du navigateur (parfois appelée "chargement de page traditionnel" ou "navigation difficile"). Ces sites Web sont parfois appelés applications multipages (MPA).
Toutefois, les développeurs peuvent contourner les paramètres par défaut des navigateurs en fonction des besoins de leur application. Cela est certainement le cas pour les sites Web qui utilisent le modèle d'application monopage (SPA), qui crée dynamiquement de grandes parties du code HTML/DOM sur le client avec JavaScript. Le rendu côté client est le nom de ce modèle de conception. Il peut avoir des effets sur l'Interaction to Next Paint (INP) de votre site Web si le travail impliqué est excessif.
Ce guide vous aidera à évaluer la différence entre l'utilisation du code HTML envoyé par le serveur au navigateur et sa création sur le client à l'aide de JavaScript, et la manière dont ce dernier peut entraîner une latence élevée des interactions à des moments cruciaux.
Comment le navigateur affiche-t-il le code HTML fourni par le serveur ?
Le schéma de navigation utilisé dans les chargements de page traditionnels implique la réception de code HTML du serveur à chaque navigation. Si vous saisissez une URL dans la barre d'adresse de votre navigateur ou 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 blocs de code HTML.
La dernière étape est essentielle. Il s'agit également de l'une des optimisations de performances les plus fondamentales dans l'échange serveur/navigateur. C'est ce que l'on appelle le streaming. Si le serveur peut commencer à envoyer du code HTML dès que possible et que le navigateur n'attend pas la réponse complète, le navigateur peut traiter le code HTML par blocs.
Comme la plupart des choses qui se produisent dans le navigateur, l'analyse du code HTML s'effectue au sein de tâches. Lorsque du code HTML est transmis du serveur au navigateur, le navigateur optimise l'analyse de ce code HTML en le faisant petit à petit, car les bits de ce flux arrivent par blocs. En conséquence, le navigateur cède périodiquement le thread principal au thread principal après le traitement de chaque fragment, ce qui évite les tâches longues. 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 Interaction to Next Paint (INP) pour la page.
Les points à retenir ? Lorsque vous diffusez du code HTML depuis le serveur, vous bénéficiez d'une analyse et d'un affichage incrémentiels du code HTML, ainsi que d'un rendement automatique sans frais dans le thread principal. Vous ne pouvez pas obtenir cela avec l'affichage côté client.
Comment le navigateur affiche-t-il le code HTML fourni par JavaScript ?
Bien que chaque requête de navigation vers une page nécessite une certaine quantité de code HTML pour être fournie par le serveur, certains sites Web utilisent le format SPA. Cette approche implique souvent qu'une charge utile initiale minimale de HTML est fournie par le serveur, puis le client remplira la zone de contenu principal d'une page avec du code HTML assemblé à partir des données extraites du serveur. Les navigations ultérieures (parfois appelées "navigations logicielles" dans ce cas) sont entièrement gérées 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 des applications Web monopages, dans des cas plus limités où le code HTML est ajouté dynamiquement au DOM via JavaScript.
Il existe plusieurs méthodes courantes pour créer du code HTML ou ajouter des éléments au DOM via JavaScript:
- La propriété
innerHTML
vous permet de définir le contenu d'un élément existant à l'aide d'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 utiliser l'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 lors de la première approche). Cependant, pour plusieurs raisons, l'utilisation dedocument.write
est vivement déconseillée.
La création de code HTML/DOM via un code 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 si vous créez trop de code HTML/DOM à la fois sur le client, cela peut avoir un impact négatif sur l'INP de votre page.
- Si le code HTML est créé sur le client au démarrage, l'outil d'analyse de préchargement du navigateur ne pourra pas détecter les ressources qui y sont référencées. Cela aura sans doute un effet négatif sur le 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 dans la récupération de ressources importantes), vous ne voulez pas que le LCP de votre site Web soit affecté par cette optimisation fondamentale des performances du navigateur.
Que pouvez-vous faire concernant l'impact sur les performances de l'affichage côté client ?
Si votre site Web dépend beaucoup du rendu côté client et que vous observez des valeurs INP faibles dans vos données de champs, vous vous demandez peut-être si l'affichage côté client est en cause. Par exemple, si votre site Web est une application monopage, vos données réelles peuvent révéler des interactions responsables d'un travail de rendu considérable.
Quelle que soit la cause, voici quelques causes possibles que vous pouvez explorer pour repartir sur de bonnes bases.
Fournir autant de code HTML que possible depuis le serveur
Comme indiqué précédemment, le navigateur gère par défaut le code HTML du serveur de manière très performante. Elle décomposera l'analyse et l'affichage du code HTML de manière à éviter les longues tâches, et à optimiser la durée totale du thread principal. Cela réduit le Total Blocking Time (TBT), qui est fortement corrélé à l'INP.
Vous utilisez peut-être un framework d'interface pour créer votre site Web. Si c'est le cas, assurez-vous d'afficher le code HTML du composant sur le serveur. Cela limitera le nombre initial d'affichage côté client nécessaire à votre site Web et devrait vous permettre d'améliorer l'expérience utilisateur.
- Pour React, vous devrez utiliser l'API Server DOM pour 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 allongement du temps de chargement du premier octet (TTFB), ainsi que des métriques ultérieures telles que First Contentful Paint (FCP) et LCP. Dans la mesure du possible, assurez-vous d'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 vers le navigateur dès que possible. Next.js, un framework basé sur React, fournit 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 des pages qui ne changent pas en fonction du contexte de l'utilisateur (comme l'authentification).
- Vue effectue également par défaut un rendu côté client. Toutefois, comme dans React, Vue peut également afficher le code HTML de votre composant sur le serveur. Si possible, exploitez ces API côté serveur ou envisagez une abstraction de niveau supérieur pour votre projet Vue afin de faciliter l'implémentation des bonnes pratiques.
- Svelte affiche le code HTML sur le serveur par défaut. Toutefois, si le code de votre composant a besoin d'accéder à des espaces de noms réservés aux navigateurs (
window
, par exemple), vous risquez de ne pas pouvoir afficher le code HTML de ce composant sur le serveur. Dans la mesure du possible, étudiez d'autres approches afin de ne pas générer inutilement un rendu côté client. SvelteKit, qui est destiné à Svelte comme Next.js l'est pour React, intègre autant de bonnes pratiques que possible dans vos projets Svelte, afin d'éviter les pièges potentiels dans les projets qui n'utilisent que Svelte.
Limitez le nombre de nœuds DOM créés sur le client.
Lorsque les DOM sont volumineux, le temps de traitement nécessaire pour les afficher a tendance à augmenter. Que votre site Web soit une SPA complète ou qu'il injecte de nouveaux nœuds dans un DOM existant à la suite d'une interaction pour une MPA, ces DOM doivent être aussi petits que possible. Cela permet de réduire le travail nécessaire lors du rendu côté client pour afficher ce code HTML, ce qui devrait permettre de réduire l'INP de votre site Web.
Envisagez d'utiliser une architecture de service worker de streaming
Il s'agit d'une technique avancée, qui peut ne pas fonctionner facilement avec tous les cas d'utilisation, mais qui peut transformer votre MPA en un site Web qui donne l'impression qu'il se charge instantanément lorsque les utilisateurs passent d'une page à l'autre. Vous pouvez faire appel à un service worker pour mettre en 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 sur le serveur.
Lorsque vous utilisez cette technique avec succès, 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 ressembler presque à une SPA, mais sans les inconvénients du rendu côté client. Cela permet également de réduire la quantité de code HTML que vous demandez au serveur.
En bref, une architecture de service worker de streaming ne remplace pas la logique de navigation intégrée du navigateur, mais l'ajoute. Pour savoir comment y parvenir avec Workbox, consultez 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 bénéficiez sans frais: l'analyse et l'affichage incrémentiels, et le retour automatique au thread principal pour éviter les longues tâches.
Le rendu 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 est impossible de l'éviter à 100% du temps. Pour réduire les longues tâches pouvant résulter d'un rendu excessif du site client, assurez-vous d'envoyer autant de code HTML de votre site Web que possible depuis le serveur, limitez au maximum la taille des DOM pour le code HTML qui doit être affiché sur le client. Envisagez également d'autres architectures pour accélérer la livraison du code HTML au client tout en tirant parti des analyses et de l'affichage incrémentiels fournis par le navigateur pour le code HTML chargé à partir du serveur.
Si vous parvenez à réduire le plus possible l'affichage côté client de votre site Web, vous améliorerez non seulement son INP, mais aussi d'autres métriques telles que le LCP, la requête large, voire votre TTFB dans certains cas.
Image principale de Unsplash, de Maik Jonietz.