
React a complètement transformé la façon dont on crée les interfaces utilisateur en introduisant une conception basée sur les composants qui favorise l’efficacité et la réutilisabilité. Sa méthode déclarative et sa structure basée sur les composants ont gagné en popularité auprès des développeurs. Mais à mesure que tes projets gagnent en complexité, tu pourrais rencontrer des problèmes de performances liés aux méthodes de rendu et de récupération des données.
Avec les méthodes traditionnelles de rendu côté client, tu comptes sur le navigateur pour exécuter du JavaScript afin d’afficher l’interface utilisateur initiale. Ça peut entraîner des retards de chargement sur les appareils aux ressources limitées. La récupération de données via une interface de programmation d’application (API) ajoute une charge supplémentaire à ces appareils, ce qui peut causer un décalage dans l’affichage du contenu et nuire à l’expérience utilisateur.
Les composants serveur offrent une solution à ces obstacles en permettant le rendu des composants sur le serveur. Ça permet au serveur de diffuser les composants vers le côté client, ce qui améliore les performances et les processus de récupération des données, puisque tout le traitement se fait sur le serveur et non sur les appareils des utilisateurs.
Dans cet article, tu découvriras comment les méthodes de rendu de React ont évolué au fil du temps, ainsi que les inconvénients liés à l’utilisation de React Suspense et du rendu côté serveur (SSR). Tu en apprendras également davantage sur les composants serveur React (RSC) et sur la manière dont ils résolvent ces problèmes.
Avant d’aborder les RSC, il est utile de comprendre les stratégies de rendu antérieures, telles que React Suspense et le SSR.
React Suspense a été introduit pour gérer le rendu asynchrone dans les applications React. Il permet aux composants de « suspendre » leur rendu jusqu’à ce que certaines conditions soient remplies, comme la récupération de données ou le fractionnement de code. Voici quelques-uns des avantages de Suspense :
React.lazy pour permettre le fractionnement de code et améliorer les performances en ne chargeant les composants que lorsqu’ils sont nécessaires.Mais React Suspense présente certaines limites dont il faut tenir compte lorsque tu fais évoluer ton application :
Suspense et ErrorBoundary, ce qui ajoute du code répétitif et rend plus difficile de garantir la cohérence et la maintenabilité de l’ensemble à mesure que ton appli se développe.Avec le SSR, les composants React sont rendus sur le serveur, puis le code HTML entièrement généré est envoyé au client pour être affiché. À l’inverse, avec le RSC, les composants individuels sont rendus dès qu’ils sont prêts, au lieu d’attendre que toute l’application se charge, comme c’est le cas avec le SSR. Cette approche présente plusieurs avantages :
Le SSR présente également des limites à prendre en compte :
Les RSC sont un nouveau type de composants dans React qui fonctionnent côté serveur, contrairement aux composants traditionnels qui fonctionnent côté client. Ils permettent de résoudre les problèmes liés à Suspense et au SSR classique en permettant aux composants d’être traités et diffusés sous forme de code HTML depuis le serveur vers le client. Les RSC gèrent également la récupération des données côté serveur, garantissant ainsi que les informations confidentielles, telles que les clés API, ne soient pas divulguées au client.
Les RSC offrent des avantages significatifs :
Par rapport aux composants côté client, les RSC gèrent l’exécution, la gestion des données et les performances différemment.
Les composants traditionnels s’exécutent dans le navigateur (côté client), où du JavaScript est nécessaire pour afficher l’interface utilisateur (UI). Les RSC s’exécutent sur le serveur en envoyant du code HTML pré-rendu à l’appareil du client au lieu de tout traiter localement. Cette approche allège la charge de travail sur l’appareil de l’utilisateur et améliore la vitesse de chargement. Gérer les mises en page et le contenu statique côté serveur est également idéal pour les composants non interactifs ou basés sur des données. Les composants côté client peuvent être imbriqués dans des RSC là où l’interactivité est nécessaire, comme pour les boutons ou les formulaires, tout en préservant la sécurité des données sensibles sur le serveur.
Les composants traditionnels peuvent augmenter la taille du bundle JavaScript côté client, ce qui peut ralentir les performances de l’appli. Les RSC n’augmentent pas la taille du package côté client puisqu’ils fonctionnent côté serveur, ce qui réduit les téléchargements et accélère le chargement des pages. Tu peux aussi utiliser les RSC pour améliorer la mise en cache. Le contenu rendu côté serveur est plus facile à mettre en cache, ce qui accélère les réponses pour les données fréquemment consultées, comme les produits populaires d’une boutique en ligne, sans avoir à interroger la base de données à plusieurs reprises.
La façon la plus simple d’utiliser les RSC en pratique, c’est via le Next.js App Router, qui prend en charge nativement les composants serveur React sans nécessiter de configuration manuelle de Webpack ou de Babel.
Note que les exemples de code de cette section utilisent Next.js 15 avec React 19.
Assure-toi d’avoir installé Node.js 22 (version LTS actuelle), puis crée un nouveau projet Next.js :
npx create-next-app@latest your-app
cd [your-app]Quand on te le demande, sélectionne l’option « App Router ». C’est important, car les RSC ne sont disponibles qu’avec l’App Router, et non avec l’ancien Pages Router.
Dans l’App Router de Next.js, chaque composant est par défaut un composant serveur. Crée un fichier à l’emplacement app/components/UserList.jsx :
// app/components/UserList.jsx
// This is a server component by default - no directive needed
async function UserList() {
// Data fetching happens on the server
// API keys and sensitive data never reach the client
const users = [
{ id: 1, name: "John Doe" },
{ id: 2, name: "Jane Smith" },
{ id: 3, name: "Alice Johnson" },
];
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
export default UserList;
Pour ajouter de l’interactivité côté client, tu dois explicitement marquer un composant avec la directive « use client ». Crée un fichier dans app/components/Counter.jsx :
// app/components/Counter.jsx
"use client"; // This directive marks it as a client component
import { useState } from "react";
function Counter({ initialCount }) {
const [count, setCount] = useState(initialCount);
return (
<div>
<button onClick={() => setCount((prev) => prev + 1)}>
Increment
</button>
<p>Count: {count}</p>
</div>
);
}
export default Counter;Maintenant, mets à jour le fichier app/page.jsx pour combiner les deux composants :
// app/page.jsx
// This is a server component - it can import both server and client components
import UserList from "./components/UserList";
import Counter from "./components/Counter";
export default function Page() {
return (
<div>
<h1>Users</h1>
<UserList /> {/* Rendered on the server */}
<Counter initialCount={50} /> {/* Interactive, runs on the client */}
</div>
);
}Lance le serveur de développement :
npm run dev
Ton application sera accessible à l'adresse http://localhost:3000. Le composant UserList s'affiche sur le serveur et transmet le code HTML au client, tandis que le composant Counter s'hydrate dans le navigateur et gère l'interactivité localement.
La principale différence par rapport à React traditionnel, c’est que UserList n’envoie pas de JavaScript au navigateur — seulement du HTML. Ça réduit la taille de ton bundle côté client et améliore automatiquement les performances de chargement.
Comme les RSC gèrent la majeure partie du rendu côté serveur, transférer autant que possible le rendu de ton application vers le serveur peut améliorer considérablement les performances tout en conservant les fonctionnalités interactives là où c’est nécessaire. Voici quelques bonnes pratiques qui peuvent t’aider à y parvenir et à améliorer la vitesse, la flexibilité et la facilité de gestion de ton application grâce aux RSC.
Tout d’abord, utilise les RSC pour récupérer des données depuis des API ou des bases de données. Si tu as déjà récupéré des données côté serveur, ne les récupère pas à nouveau côté client. Par exemple, si tu charges des données utilisateur côté serveur et que tu les transmets au client, il n’y a pas besoin d’un deuxième appel d’API côté client, sauf si les données changent.
Décomposer le code en petits morceaux et charger de manière sélective les scripts nécessaires à l’aide d’outils tels que Vite ou webpack peut contribuer à améliorer les temps de chargement. Crée des composants réutilisables dans toute ton application. Par exemple, si plusieurs pages doivent afficher une liste d’utilisateurs, crée un composant « UserList » qui fonctionne partout.
Enfin, veille à ce que les composants serveur restent légers en les consacrant exclusivement au rendu des données, puisqu’ils n’ont pas besoin de gérer l’état comme le font les composants client. Concentre-toi sur leur légèreté et sur leur rôle exclusif de rendu des données. N’hydrate que les parties d’une page qui doivent être interactives. Par exemple, si la page est principalement statique mais comporte un formulaire ou un bouton interactif, n’hydrate que ces composants.
Même si les RSC présentent des avantages, il est aussi important de comprendre les obstacles et les limites liés à leur intégration dans ton projet.
Les composants côté serveur ne peuvent pas interagir avec les méthodes de cycle de vie telles que `useEffect` ou `useState`. Ça veut dire que tu ne peux pas gérer l’interactivité côté client au sein des composants côté serveur. Par exemple, si un formulaire est affiché côté serveur, tu auras besoin d’un composant côté client pour gérer les modifications en temps réel des données saisies.
Lorsque tu utilises à la fois des composants côté client et côté serveur dans tes projets, il est important de gérer l’interaction entre ces deux types de composants dans toute ton application pour éviter tout problème. Par exemple, si ton application récupère des données depuis le serveur et permet aux utilisateurs de modifier ces données localement sur leurs appareils, tu risques de rencontrer des problèmes pour maintenir la cohérence des données entre le serveur et les composants côté client.
Les composants côté serveur ne peuvent utiliser que des props sérialisables, ce qui signifie que tu ne peux pas passer de fonctions, de symboles ou d’objets complexes qui ne peuvent pas être sérialisés. Par exemple, envoyer une fonction de rappel d’un composant côté serveur vers un composant côté client entraînera un message d’erreur. Les composants côté serveur n’ont pas accès aux API du navigateur telles que window, document ou localStorage. Si tu as besoin d’interagir avec le DOM, cela doit se faire dans un composant côté client.
Si le code HTML affiché par le serveur ne correspond pas à ce qu’attend le JavaScript côté client, ça peut poser des problèmes pendant le processus d’hydratation. Par exemple, des différences dans le formatage des dates entre le serveur et le client peuvent entraîner de légers décalages. Les décalages d’hydratation peuvent être difficiles à déboguer, car la cause première n’est pas toujours évidente.
Certaines bibliothèques tierces peuvent ne pas fonctionner correctement avec les RSC, en particulier celles qui dépendent fortement des techniques de rendu côté client ou d’API spécifiques aux navigateurs. Par exemple, des bibliothèques telles que react-router-dom nécessitent un rendu côté client. Tu devras peut-être remplacer ou adapter certaines bibliothèques pour qu’elles fonctionnent avec les RSC.
Il existe des solutions pratiques que tu peux mettre en œuvre pour garantir la cohérence et résoudre les problèmes courants liés au RSC.
Utilise des outils de gestion d’état qui fonctionnent à la fois côté serveur et côté client, comme Redux ou Zustand. Ces bibliothèques te permettent de centraliser ton état afin que les composants rendus côté serveur et ceux côté client puissent accéder aux mêmes données. Par exemple, tu pourrais utiliser Redux pour stocker un état global accessible aux deux côtés de l’application.
Veille à maintenir un flux de données entre le serveur et le client en partageant le contexte. Par exemple, lorsque tu transfères des données utilisateur entre les composants serveur et client, assure-toi que les informations sont gérées de manière centralisée pour éviter toute incohérence.
Pense à utiliser des outils de développement ou des linters de code pour identifier les propriétés non sérialisables qui pourraient poser problème avec les RSC. Par exemple, des outils comme ESLint peuvent être configurés pour détecter les props de fonction transmises depuis des composants côté serveur.
Veille à refactoriser les composants pour t'assurer que les props peuvent être sérialisées et éviter tout problème avec le SSR. Une façon d’y parvenir consiste à déplacer certaines opérations, comme les gestionnaires d’événements, vers les composants côté client. Par exemple, lorsque tu transmets une fonction de rappel depuis un composant côté serveur, assure-toi que le code est adapté pour que l’opération se déroule au sein du composant côté client où elle est utilisée.
Pour résoudre les incohérences d'hydratation, il faut recourir à des techniques de test et de débogage proactives :
Si un logiciel tiers ne fonctionne pas avec les composants serveur comme l’exigent les spécifications de ton projet, explore d’autres options compatibles avec le serveur. Si tu utilises une bibliothèque open source pour ton projet, tu pourrais envisager de contribuer à son développement afin d’y inclure également la prise en charge des RSC. En contribuant ainsi, tu peux améliorer ta propre application tout en ayant un impact positif sur la communauté au sens large qui s’appuie sur cette même bibliothèque pour son travail.
En relevant ces défis grâce à des stratégies adaptées, tu pourras contourner efficacement les limites des RSC et créer des applications robustes et performantes.
Dans cet article, on a expliqué les techniques de rendu de React. On a présenté React Suspense et le SSR, et on a proposé un guide plus approfondi sur les RSC. Tu peux utiliser les RSC pour améliorer les performances de ton application en réduisant le traitement JavaScript côté client et en accélérant le chargement initial des pages.
Si tu veux tester les RSC dans tes projets, la première étape consiste à identifier les composants de ton application qui pourraient tirer parti du SSR. Tu pourras ensuite intégrer progressivement les RSC dans ton code.
La gestion de l’infrastructure pour le SSR et les composants serveur peut s’avérer complexe. L’utilisation d’Upsun, une plateforme en tant que service (PaaS), simplifie le déploiement et la mise à l’échelle de tes applications React. Grâce à sa prise en charge intégrée de Node.js et à sa scalabilité automatique, Upsun peut t’aider à gérer en douceur les pics de trafic. Il fournit également des outils de surveillance et de sécurité et te permet de gérer plusieurs applications ou microservices dans différents langages au sein d’un même projet. Ainsi, tu peux te concentrer sur le développement de ton application React tandis qu’Upsun s’occupe de l’infrastructure de base.