React Server Components : Une Plongée Pratique
Comment les frontières RSC, le streaming et la séparation client/serveur fonctionnent dans l'App Router Next.js — et quand utiliser un composant client.
Les React Server Components représentent l'un des changements architecturaux les plus significatifs de l'écosystème React depuis les hooks. Associés au App Router de Next.js, ils permettent de rendre les composants sur le serveur par défaut, d'envoyer uniquement la sortie sérialisée au client et de réserver le JavaScript côté client aux interactions qui en ont réellement besoin. Comprendre où les composants serveur s'arrêtent et où les composants client commencent est essentiel pour construire des applications rapides et maintenables en 2026.
Que sont les React Server Components ?
Les React Server Components, souvent abrégés RSC, sont des composants qui s'exécutent exclusivement sur le serveur lors d'une requête ou au moment du build. Contrairement au rendu côté serveur traditionnel, qui hydrate l'intégralité de la page côté client, les RSC envoient une représentation sérialisée compacte appelée payload React Flight. Le client reçoit ce payload et reconstruit l'interface sans télécharger le code source du composant ni ses dépendances.
Ce modèle offre plusieurs avantages pratiques pour les applications en production :
- Taille de bundle réduite — Les dépendances réservées au serveur ne sont jamais envoyées au navigateur.
- Accès direct aux données — Les composants peuvent interroger bases de données et systèmes de fichiers sans exposer les identifiants via des routes API.
- Découpage automatique du code — Chaque frontière de composant serveur crée un point de séparation naturel.
- Time to First Byte amélioré — Le streaming permet d'afficher la coque pendant que les données plus lentes se résolvent.
Le modèle mental est simple : considérez les composants serveur comme la couche de rendu par défaut et les composants client comme des îlots d'interactivité optionnels répartis dans l'arbre.
Comprendre les frontières RSC dans Next.js
Dans le App Router de Next.js, chaque fichier du répertoire app est un Server Component, sauf si vous ajoutez la directive "use client" en haut du fichier. Cette directive crée une frontière client. Tout ce qui est importé par ce fichier fait partie du bundle client, et les enfants passés en props peuvent toujours être rendus côté serveur grâce à une technique appelée composition.
Composition à travers les frontières
L'un des modèles les plus puissants consiste à passer des composants serveur en tant qu'enfants à des composants client. Le composant serveur est rendu en premier, et sa sortie est diffusée dans l'emplacement du composant client. Cela évite le piège courant de marquer une page entière comme composant client simplement parce qu'une petite section nécessite un état ou des gestionnaires d'événements.
// ServerComponent.tsx (no directive — runs on server)
async function ProductList() {
const products = await db.query("SELECT * FROM products");
return (
<ul>
{products.map((p) => (
<li key={p.id}>{p.name}</li>
))}
</ul>
);
}
// ClientWrapper.tsx
"use client";
export function ClientWrapper({ children }: { children: React.ReactNode }) {
const [expanded, setExpanded] = useState(false);
return (
<div>
<button onClick={() => setExpanded(!expanded)}>Toggle</button>
{expanded && children}
</div>
);
}
// page.tsx (Server Component)
export default function Page() {
return (
<ClientWrapper>
<ProductList />
</ClientWrapper>
);
}
Notez que ProductList ne devient jamais un composant client même s'il se trouve dans un wrapper interactif. Le serveur le rend, sérialise le résultat, et le client reçoit le balisage final.
Streaming et Suspense
Next.js exploite les capacités de streaming de React pour envoyer le HTML au navigateur de manière incrémentale. Lorsque vous enveloppez des composants serveur asynchrones dans des frontières <Suspense>, le framework peut afficher immédiatement une interface de secours pendant que les sections plus lentes se résolvent en arrière-plan.
Le streaming est particulièrement efficace pour les pages avec des sources de données hétérogènes. Une couche de cache rapide peut se résoudre en millisecondes tandis qu'une requête d'agrégation complexe prend plusieurs secondes. Sans streaming, l'utilisateur fixe un écran vide jusqu'à la fin de tout. Avec le streaming, la navigation, la mise en page et le contenu en cache apparaissent instantanément.
- Placez des frontières
<Suspense>autour des zones de récupération de données indépendantes. - Utilisez une interface de secours significative — les squelettes de chargement surpassent les spinners génériques.
- Imbriquez les frontières pour un contrôle granulaire de ce qui est diffusé en premier.
- Combinez avec les fichiers
loading.tsxpour des fallbacks au niveau des routes.
La combinaison des RSC et du streaming change fondamentalement la façon dont vous pensez les performances de chargement. Au lieu d'optimiser une seule cascade de requêtes, vous concevez les pages comme une série de segments diffusables indépendamment.
Quand utiliser les Client Components
Malgré le défaut serveur en premier, les composants client restent indispensables. Toute fonctionnalité qui repose sur les API du navigateur, l'état local, les effets ou les gestionnaires d'événements nécessite la frontière client. L'objectif n'est pas d'éliminer les composants client mais de minimiser leur empreinte.
Optez pour "use client" lorsque vous avez besoin de l'un des éléments suivants :
- Gestionnaires d'événements — onClick, onChange, onSubmit et interactions DOM similaires.
- Hooks React — useState, useEffect, useReducer, useContext et hooks personnalisés qui en dépendent.
- API réservées au navigateur — localStorage, géolocalisation, IntersectionObserver et Web Audio.
- Bibliothèques tierces — De nombreuses bibliothèques de graphiques, cartographie et animation supposent un environnement navigateur.
Une heuristique pratique consiste à repousser la frontière client aussi bas que possible dans l'arbre des composants. Au lieu de marquer une page de tableau de bord entière comme composant client, extrayez le graphique interactif ou le panneau de filtres dans une petite île client et gardez la mise en page, les en-têtes et les tableaux de données sur le serveur.
Modèles de récupération de données
Les composants serveur peuvent récupérer des données directement avec async/await au niveau du composant. Il n'est pas nécessaire d'utiliser useEffect ou une bibliothèque de récupération de données distincte pour les lectures côté serveur. Next.js étend cela avec des sémantiques de cache via l'API fetch et l'assistant unstable_cache.
// Direct async fetch in a Server Component
async function BlogPost({ slug }: { slug: string }) {
const post = await fetch(`https://api.example.com/posts/${slug}`, {
next: { revalidate: 3600 },
}).then((res) => res.json());
return (
<article>
<h1>{post.title}</h1>
<p>{post.body}</p>
</article>
);
}
Pour les mutations, les Actions de React 19 s'intègrent naturellement aux composants serveur. Vous définissez des server actions avec la directive "use server" et les invoquez depuis des formulaires client sans construire manuellement des points de terminaison API. Cela boucle le rendu serveur et les mutations côté serveur de manière typée et colocalisée.
Pièges courants et bonnes pratiques
Les équipes nouvelles aux RSC rencontrent souvent des erreurs récurrentes. Passer des valeurs non sérialisables comme des fonctions ou des instances de classe des composants serveur aux composants client provoque des erreurs d'exécution. Importer des modules réservés au serveur dans des composants client entraîne des échecs de build. Et marquer de grands arbres de composants comme composants client annule entièrement le but de l'architecture.
Adoptez ces pratiques pour rester sur la bonne voie :
- Gardez les composants serveur par défaut et ajoutez les frontières client de manière ciblée.
- Colocalisez la récupération de données avec les composants qui consomment les données.
- Utilisez TypeScript pour détecter les problèmes de sérialisation à la compilation.
- Profilez régulièrement votre bundle client pour vous assurer que les composants serveur remplissent leur rôle.
- Documentez les décisions de frontière dans votre codebase pour que l'équipe maintienne la cohérence.
Les React Server Components ne sont pas une solution miracle, mais ils offrent un modèle cohérent pour construire des applications rapides par défaut. Maîtriser les frontières, le streaming et le modèle de composition serveur-client portera ses fruits sur chaque projet livré avec le App Router de Next.js.
Cette lecture vous a plu ?
Un projet ou une idée en tête ? J'aimerais beaucoup en discuter.
Me contacter