Le Rendu Arc-en-ciel dans Next.js

Eric Burel
PointJS
Published in
9 min readJan 30, 2024

--

L’architecture pour la mise en place du rendu arc-en-ciel, qui incidemment à clairement la forme d’une tête de licorne.

Le prérendu statique est un principe clé de la Jamstack

La Jamstack est une façon de structurer les applications web en combinant du code JavaScript, des APIs, et du “Markup”.

Une idée clé de la Jamstack est le prérendu, c’est-à-dire que les pages web doivent être fournies sous forme de HTML dès que cela est possible, même si vous utilisez un framework JavaScript moderne tel que React.

Pour cela, il est nécessaire de mettre en place le prérendu statique de l’application dès que possible, c’est-à-dire générer les pages une fois pour toute au moment de la compilation, juste avant de mettre le site en ligne.

Grâce au prérendu statique, il est possible d’envoyer directement du HTML au navigateur client, le site semble plus rapide.

Le SaaS et la Jamstack sont difficilement compatibles

D’un autre côté, le SaaS, pour Software as a Service, est un mode de distribution des logiciels via le web. Plutôt que de vendre des CD d’installation comme le faisaient nos ancêtres, les entreprises créent des applications web complexes accessibles depuis le navigateur : Gmail, Microsoft Office 365, Figma…

Mais il y a un problème : les applications SaaS sont un contexte très défavorable pour le prérendu statique. Ces applications tendent à ne pas respecter les principes de la philosophie Jamstack.

Une application SaaS est l’inverse de ce que l’on appelle une application de contenu comme un blog ou un ecommerce par exemple. Dans un blog ou un ecommerce, il y a un grand nombre de pages publiques, avec des données publiques. C’est l’idéal pour le rendu au moment de la compilation, qu’on appelle aussi “static site generation (SSG)”.

Dans un logiciel, il y a au contraire peu de pages, avec beaucoup de données privées. Au mieux, on peut pré-générer un squelette de page sans données, en suivant le principe “secure data, not pages” popularisé par Blitz.js. C’est par exemple l’architecture du tableau de bord de Vercel.

Ce squelette de page est rempli de données côté client, dans le navigateur de l’utilisateur : elles paraîtront toujours plus lentes que des pages entièrement publiques.

Les technologies de rendu statique n’ont pas été crées pour afficher des données privées. C’est logique, car pour afficher des données privées, il faut avoir une idée approximative de qui peut accéder à ces données, donc de quel utilisateur va accéder au site. Mais ça, on ne peut pas le savoir à l’avance, au moment de la compilation.

Cela veut aussi dire qu’il faut avoir un serveur à disposition pour sécuriser l’accès aux pages, ce que certains frameworks Jamstack ne proposent pas.

Tout ça, c’était avant le rendu arc-en-ciel.

“Et si je te disais que tu peux en fait faire un prérendu statique d’applications SaaS avec des données privées”

Un rendu statique de plusieurs versions d’une même page

Il y a en fait de nombreuses situations intermédiaires entre :

  • une page qui affiche des données spécifiques à un utilisateur, qui nécessite soit du rendu côté client soit du rendu serveur à la requête (ce qu’on appelle le SSR ou rendu dynamique),
  • et une page qui est la même pour tous les utilisateurs, qui peut être générée statiquement (ce qu’on appelle le SSG ou rendu statique).

Un cas d’usage très classique où il est nécessaire de générer plusieurs versions d’une même page est l’internationalisation, c’est-à-dire la traduction d’un site. Les utilisateurs voient la même page seulement s’ils parlent le même langage, il y a une forme de personnalisation du contenu.

Du point de vue du développeur, l’objectif est de générer une version de chaque page pour chaque langage disponible dans l’application.

Un autre : les applications SaaS sont souvent “multi-tenant” ou multi-organisations. Une entreprise cliente de l’application peut vouloir personnaliser certains éléments, comme afficher son logo au dessus des pages. Tous les employés d’une même entreprise qui utilisent l’application devraient voir le logo de leur entreprise.

Donc, les paramètres de personnalisation comme le thème, le langage, l’organisation à laquelle l’utilisateur appartient sont des candidats potentiels pour un rendu statique, qui permet un affichage immédiat du contenu.

Mais il ne s’agit pas de contenus identiques pour tous les utilisateurs, ni de contenus spécifiques à chaque utilisateur, on est quelque part entre le “SSG” et le “SSR”.

Le problème de l’URL longue

Une stratégie classique pour pour générer de telles variations d’une page à l’avance, avec un rendu statique, est de créer une URL par version.

Par exemple “/accueil/societe-truc/theme-sombre/fr” serait la page d’accueil de l’entreprise Truc International, en français, avec un thème sombre, tandis que “/accueil/societe-machin/theme-clair/it” serait la page d’accueil de la société Machin SARL, en italien, avec un fond blanc.

Le problème est que dans les frameworks actuels, la génération statique s’appuie beaucoup sur l’URL, ce n’est pas très élégant. Qu’en est-il des cookies, des en-têtes de requêtes HTTP, des paramètres d’URL ? Toutes ces informations pourraient nous aider à personnaliser le site, sans forcément surcharger l’URL.

Longue vie au rendu statique

A l’heure actuelle, dans ces situations, les développeurs ont tendance à utiliser soit du rendu côte client, soit du rendu serveur à la requête, qui impliquent soit un temps de chargement pour l’utilisateur, soit un rendu coûteux pour chaque requête. Si seulement nous pouvions utiliser le rendu statique, qui est moins cher et plus rapide !

J’ai prouvé mathématiquement que la façon actuelle de faire de la génération statique à partir de l’URL n’exploite pas du tout les capacités maximales du rendu statique.

On peut mesurer cette capacité en nombre minimal de rendu qu’il faut pour générer les pages d’un site, dans toutes les versions visibles par les utilisateurs. Le lien complet est ici : https://tinyurl.com/ssr-theory.

“Et si je te disais qu’il n’y a pas besoin d’encombrer l’URL pour implémenter le rendu statique”

Le Rendu Arc-en-ciel

J’ai inventé un terme pour définir l’architecture qui résout tout ces problèmes : le rendu arc-en-ciel ou Rainbow Rendering.

Pourquoi arc-en-ciel ? Parce que cette architecture permet de générer une même page, en plusieurs couleurs.

Techniquement, le rendu arc-en-ciel est une forme de génération statique qui s’appuie sur tous les paramètres de la requête HTTP — cookies, en-têtes- et pas uniquement les paramètres de route de l’URL.

Certains diront : “ok, mais au moment de la compilation, je ne connais pas les requêtes HTTP qui seront émises par les utilisateurs qui accèdent au site, je ne peux donc pas utiliser les cookies ou les en-têtes HTTP pendant un rendu statique”.

Oui, mais en fait non. Le simple fait d’utiliser l’URL pour configurer le rendu statique, suppose déjà de façon implicite que les utilisateurs vont émettre des requêtes HTTP vers ces URL lorsqu’ils se connecteront au site.

Il y a donc bien des requêtes HTTP même pendant la compilation statique du site avant sa mise en ligne, elles sont juste cachées !

La confusion découle du fait que nous avons pris l’habitude de n’utiliser que 10% de cette requête “implicite”, l’URL, et de jeter les 90% qu’il reste. Un peu dommage de jeter autant de cookies !

“Et si je te disais que le rendu statique se repose implicitement sur l’existence d’une requête HTTP puisqu’il utilise l’URL”

Que ce passe-t-il une fois le site mis en ligne ?

Il faut un serveur de redirection

Imaginons que l’on génère les pages du site pour chaque valeur possible d’un cookie ou d’une en-tête HTTP, par exemple les en-têtes Accept-Language qui indiquent le langage de l’utilisateur.

Comment faire sorte ensuite que chaque utilisateur voie la page dans la bonne langue ?

Il y a une petite condition pour que le rendu arc-en-ciel puisse fonctionner en pratique : il faut mettre en place un micro-serveur de redirection ou de réécriture d’URL.

Une réécriture d’URL c’est exactement comme une redirection, sauf que l’utilisateur final ne voit pas la nouvelle URL. Pour le langage, on préfère souvent une redirection en affichant le code de la langue dans l’URL (“/fr”) alors que pour un test A/B, une réécriture d’URL est nécessaire (on ne veut pas que l’utilisateur sache s’il est dans le groupe de test ou le groupe de traitement).

Bien sécuriser l’accès à des données privées

Il est très important que cette redirection se fasse côté serveur dans le cas où des données privées sont affichées.

Le rendu arc-en-ciel permet de faire un prérendu statique de n’importe quelles données qui sont partagées entre plusieurs utilisateurs, potentiellement des données privées.

Il peut par exemple s’agir de la version payante d’un article, accessible uniquement aux utilisateurs qui ont un abonnement. Dans le cas de la multi-tenancy, vous ne voulez certainement pas que les employés de la société Truc International aient accès au contenu de la société Machin SARL !

Il faut toujours sécuriser la redirection, en gardant en tête qu’un cookie peut toujours être défini manuellement par un utilisateur malveillant, il faut par exemple comparer la valeur du cookie avec une valeur en base de données.

J’insiste sur ce cas car on ne se rend pas compte de ce problème quand on raisonne en termes d’URL. Tout le monde sait que l’utilisateur final peut modifier l’URL à sa guise dans le navigateur, on peut par contre oublier qu’il peut aussi modifier ses cookies ou les en-têtes HTTP, qui sont utilisées dans le cas du rendu arc-en-ciel.

Bien sûr, dans le cas où les données sont publiques, cela est moins compliqué, par exemple ce n’est pas grave si un utilisateur allemand accède au texte en français d’un article public.

L’architecture finale

Le micro-serveur de redirection a donc deux rôles :

  • sécuriser l’accès à la page
  • rediriger l’utilisateur vers la bonne version de la page

J’ai choisi une licorne pour représenter le rendu arc-en-ciel, car ce micro-serveur, c’est un peu comme une corne de licorne : c’est lui qui apporte la magie !

La licorne du Rendu Arc-en-Ciel, vue d’au-dessus.

Le Rendu Arc-en-ciel se fait donc en 3 étapes :

  1. Le rendu de différentes versions de la même page grâce au serveur de rendu, par exemple Next.js
  2. L’analyse de la requête et la sécurisation de l’accès avec un micro-serveur
  3. La redirection vers la bonne version de la page

Et voilà !

Comment implémenter le rendu arc-en-ciel ?

Quand j’ai écrit la première version en anglais de cet article en 2021 (Let’s bring the Jamstack to SaaS: introducing Rainbow Rendering), il fallait utiliser un serveur proxy tel qu’Apache ou Nginx pour faire la redirection.

Mais quelques mois plus tard, les middlewares ont été ajoutés à Next : ils sont parfaits pour implémenter le rendu arc-en-ciel !

Cette architecture est devenue depuis assez courante, c’est comme cela que Vercel recommande d’implémenter les tests A/B.

Dans un prochain article, je vous montrerai des patterns avancés que l’on peut construire à partir du rendu arc-en-ciel : comment gérer un grand nombre de paramètres avec [M] (le Mégaparam, pas le chanteur) ou encore comment reproduire le rendu arc-en-ciel avec le cache HTTP.

Quelques ressources pour approfondir

Découvrez ma formation Next.js en 3 jours

Mes masterclass en 1 journée sur des sujets spécifiques

Une playlist Youtube où l’on suit le tutoriel Next.js Learn, en français

Et mes cours vidéos (en anglais)

Découvrez ma formation vidéo “Next.js Patterns”: https://course.nextjspatterns.com/manage-client-only-code-in-next-js-with-react-browser-components

--

--

Eric Burel
PointJS

Next.js teacher and course writer. Co-maintainer of the State of JavaScript survey. Follow me to learn new Next.js tricks ✨ - https://nextjspatterns.com/