Affichage côté client du code HTML et de l'interactivité

Le rendu HTML avec JavaScript est différent du rendu HTML envoyé par le serveur, ce qui peut affecter les performances. Découvrez la différence dans ce guide et ce que vous pouvez faire pour préserver les performances de rendu de votre site Web, en particulier en ce qui concerne les interactions.

L'analyse et le rendu du code HTML sont des tâches que les navigateurs effectuent très bien par défaut pour les sites Web qui utilisent la logique de navigation intégrée du navigateur (parfois appelée "chargement de page traditionnel" ou "navigation forcée"). Ces sites Web sont parfois appelés applications multipages (MPA).

Toutefois, les développeurs peuvent contourner les valeurs par défaut du navigateur pour répondre aux besoins de leur application. C'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 HTML/DOM côté client avec JavaScript. Ce modèle de conception s'appelle le rendu côté client. Il peut avoir un impact sur l'interaction jusqu'à la prochaine peinture (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 avec JavaScript, et à comprendre comment ce dernier peut entraîner 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 pages traditionnels implique de recevoir du 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:

  1. Le navigateur envoie une requête de navigation pour l'URL fournie.
  2. Le serveur répond avec du code HTML par blocs.

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, et est appelé streaming. Si le serveur peut commencer à envoyer du code HTML dès que possible et que le navigateur n'attend pas que la réponse complète arrive, il peut traiter le code HTML par blocs à mesure qu'il arrive.

Capture d'écran de l'analyse du code HTML envoyé par le serveur, visualisée dans le panneau "Performances" de Chrome DevTools. Lorsque le code HTML est diffusé, des fragments sont traités dans plusieurs tâches plus courtes, et le rendu est incrémentiel.
Analyse et rendu du code HTML fourni par le serveur, comme illustré dans le panneau "Performances" des outils pour les développeurs Chrome. Les tâches liées à l'analyse du code HTML et à son rendu sont divisées en blocs.

Comme la plupart des choses qui se passent dans le navigateur, l'analyse HTML se produit dans les tâches. Lorsque le code HTML est diffusé en streaming du serveur vers le navigateur, le navigateur optimise l'analyse de ce code en effectuant l'analyse par bit à la fois, car les bits de ce flux arrivent par blocs. Par conséquent, le navigateur cède régulièrement 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 de rendu 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.

Le point à retenir ? Lorsque vous diffusez du code HTML à partir du serveur, vous bénéficiez d'une analyse et d'un rendu incrémentaux du code HTML, ainsi que d'un transfert automatique au thread principal sans frais. 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 requête de navigation vers une page nécessite que le serveur fournisse une certaine quantité de code HTML, certains sites Web utilisent le modèle SPA. Cette approche implique souvent qu'une charge utile HTML initiale minimale est 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. Les navigations ultérieures (parfois appelées "navigations douces" dans ce cas) sont entièrement gérées par JavaScript pour renseigner la page avec du nouveau code HTML.

L'affichage côté client peut également se produire dans des cas plus limités dans les applications autres que les SPA, lorsque le code HTML est ajouté de manière dynamique 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:

  1. 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.
  2. La méthode document.createElement vous permet de créer des éléments à ajouter au DOM sans utiliser d'analyse HTML du navigateur.
  3. La méthode document.write vous permet d'écrire du code HTML dans le document (et le navigateur l'analyse, comme dans l'approche 1). Toutefois, pour plusieurs raisons, l'utilisation de document.write est vivement déconseillée.
Capture d'écran de l'analyse du code HTML généré via JavaScript, visualisée dans le panneau "Performances" de Chrome DevTools. Le travail s'effectue dans une seule tâche longue qui bloque le thread principal.
Analyse et rendu du code HTML via JavaScript sur le client, comme illustré dans le panneau "Performances" des outils pour les développeurs Chrome. Les tâches impliquées dans l'analyse et le rendu ne sont pas segmentées, ce qui entraîne une tâche longue qui bloque le thread principal.

Les conséquences de la création de HTML/DOM via JavaScript côté client peuvent être 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 segmentées, ce qui peut entraîner des tâches longues qui bloquent le thread principal. Cela signifie que l'INP de votre page peut être affecté négativement si vous créez trop de HTML/DOM à la fois sur le client.
  • Si du 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 de préchargement du navigateur. Cela aura certainement un impact 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 (il s'agit plutôt d'un problème de retard réseau lors de l'extraction de ressources importantes), vous ne souhaitez pas que le LCP de votre site Web soit affecté par le fait de contourner cette optimisation fondamentale des performances du navigateur.

Que faire pour réduire l'impact du rendu côté client sur les performances ?

Si votre site Web dépend fortement du rendu côté client et que vous avez observé des valeurs INP médiocres dans vos données de champ, vous vous demandez peut-être si le rendu côté client est en cause. Par exemple, si votre site Web est une application SPA, vos données de champ peuvent révéler des interactions responsables d'un travail de rendu considérable.

Quelle que soit la cause, voici quelques raisons possibles qui peuvent vous aider à rétablir la situation.

Fournissez autant de code HTML que possible à partir du serveur

Comme indiqué précédemment, le navigateur gère le code HTML du serveur de manière très performante par défaut. Il divise l'analyse et le rendu du code HTML de manière à éviter les tâches longues et à optimiser la durée totale du thread principal. Cela permet de réduire le temps d'arrêt total (TBT), qui est fortement corrélé à l'INP.

Vous pouvez utiliser un framework front-end pour créer votre site Web. Dans ce cas, assurez-vous d'afficher le code HTML du composant sur le serveur. Cela limitera la quantité de rendu côté client initial requise par votre site Web, ce qui devrait améliorer l'expérience utilisateur.

  • Pour React, vous devez utiliser l'API DOM du serveur pour afficher du code HTML sur le serveur. Toutefois, sachez que la méthode traditionnelle de rendu côté serveur utilise une approche synchrone, ce qui peut entraîner un temps de latence du premier octet (TTFB) plus long, ainsi que des métriques ultérieures telles que le First Contentful Paint (FCP) et le 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 contenu 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 de générer automatiquement du code HTML sur le serveur, il peut également générer de manière statique du code HTML pour les pages qui ne changent pas en fonction du contexte utilisateur (comme l'authentification).
  • Vue effectue également le rendu côté client par défaut. Cependant, comme React, Vue peut également rendre le code HTML de votre composant sur le serveur. Profitez de 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 l'implémentation des bonnes pratiques.
  • Par défaut, Svelte affiche le code HTML sur le serveur. Toutefois, si le code de votre composant a besoin d'accéder à des espaces de noms exclusifs 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, explorez d'autres approches afin de ne pas générer de rendu côté client inutile. SvelteKit, qui est à Svelte ce que Next.js est à React, intègre autant que possible de bonnes pratiques dans vos projets Svelte. Vous pouvez ainsi éviter les écueils potentiels des projets qui utilisent uniquement Svelte.

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 complète ou qu'il injecte de nouveaux nœuds dans un DOM existant à la suite d'une interaction pour une MPA, envisagez de réduire ces DOM autant que possible. Cela permet de réduire le travail requis lors du rendu côté client pour afficher ce code HTML, ce qui devrait contribuer à réduire l'INP de votre site Web.

Envisager une architecture de worker de service 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 site Web qui semble se charger instantanément lorsque les utilisateurs passent d'une page à l'autre. Vous pouvez utiliser un service worker pour pré-cacher les parties statiques de votre site Web dans CacheStorage tout en utilisant l'API ReadableStream pour extraire le reste du code HTML d'une page à partir du serveur.

Lorsque vous utilisez cette technique, vous ne créez pas de code HTML sur le client, mais le chargement instantané des parties du contenu à partir du cache donne 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. Cela réduit également la quantité de code HTML que vous demandez au serveur.

En résumé, une architecture de nœud de calcul de service de streaming ne remplace pas la logique de navigation intégrée du navigateur, mais s'y ajoute. Pour savoir comment procéder avec Workbox, consultez Applications multipages plus rapides avec des flux.

Conclusion

La façon dont votre site Web reçoit et affiche le code HTML a un impact sur ses performances. Lorsque vous vous appuyez sur le serveur pour envoyer l'ensemble (ou la majeure partie) du code HTML requis pour le fonctionnement de votre site Web, vous bénéficiez de nombreux avantages sans frais: analyse et rendu incrémentaux, et cession automatique au thread principal pour éviter les tâches longues.

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. Toutefois, en raison des exigences de chaque site Web, il n'est pas possible de l'éviter à 100 %. Pour atténuer les tâches potentiellement longues qui peuvent résulter d'un rendu excessif sur le site client, assurez-vous d'envoyer autant que possible le code HTML de votre site Web à partir du serveur, réduisez autant que possible la taille de votre DOM pour le code HTML qui doit être rendu sur le client, et envisagez d'autres architectures pour accélérer la diffusion du code HTML auprès du client tout en profitant de l'analyse et du rendu incrémentaux que le navigateur fournit pour le code HTML chargé à partir du serveur.

Si vous pouvez réduire au maximum le rendu côté client de votre site Web, vous améliorerez non seulement son INP, mais aussi d'autres métriques telles que le LCP, le TBT et, dans certains cas, le TTFB.

Image principale issue de Unsplash, par Maik Jonietz.