Server Components
Définition
Composants React rendus côté serveur uniquement. Permettent d'aller chercher des données directement dans le composant sans envoyer de JavaScript au client, ce qui allège fortement le bundle.
Comment ça marche
Un Server Component s'exécute uniquement sur le serveur, au moment du rendu. Il peut interroger directement la base de données, lire un fichier, appeler une API privée avec une clé secrète, sans jamais exposer ce code au navigateur. Le résultat est sérialisé en une représentation intermédiaire envoyée au client, puis rendue en HTML. Le code source du composant et ses dépendances n'arrivent jamais dans le bundle JavaScript expédié à l'utilisateur. C'est une évolution majeure de React, popularisée par Next.js App Router à partir de 2023.
Le gain principal
Le bénéfice immédiat : un bundle JavaScript bien plus léger côté client. Toutes les bibliothèques utilisées uniquement pour le rendu (Markdown, formatage, requêtes base, parsing) restent côté serveur. Sur un site Next.js classique, on passe souvent de 300-500ko de JS à 50-100ko, ce qui change radicalement le LCP et l'INP sur mobile. Pour les sites SEO, où Google note la performance comme critère de classement, c'est un avantage direct. Pour les apps interactives, c'est moins critique mais reste bénéfique.
La frontière serveur/client
Tout composant App Router est serveur par défaut. On bascule en Client Component en ajoutant "use client" en tête de fichier, ce qui marque la frontière. Une fois cette frontière franchie, tous les composants enfants du Client Component sont également côté client. La règle pratique : commencer par un Server Component partout, et ne basculer en client qu'au moment où on a besoin d'un hook React (useState, useEffect), d'un event handler (onClick, onChange) ou d'une API navigateur (window, localStorage). Le but est de garder les Client Components aussi petits et profonds dans l'arbre que possible.
Composer serveur et client
On compose librement Server Components et Client Components, à condition de respecter une règle : un Server Component ne peut pas être importé dans un Client Component, mais peut être passé en props (children, slot) à un Client Component. Cette astuce permet de garder du contenu serveur à l'intérieur d'un wrapper interactif. Exemple typique : un modal Client Component qui reçoit en children un Server Component qui charge des données. Cette composition prend l'habitude, mais permet des architectures très efficaces une fois maîtrisée.
Les limites à connaître
Un Server Component ne peut pas utiliser de hooks React (pas d'état, pas d'effet), ni d'event handlers (pas d'onClick), ni accéder aux API navigateur. Il ne peut donc pas être interactif. Si on importe une bibliothèque qui utilise des hooks (Framer Motion, certains UI kits), on doit la wrapper dans un Client Component. Certaines libs anciennes mal packagées ne marquent pas leurs entrées et provoquent des erreurs cryptiques au build. La compatibilité s'est massivement améliorée depuis 2024, mais on vérifie chaque dépendance avant adoption.
Les pièges à éviter
Quatre pièges classiques. Importer un composant client dans un composant serveur sans raison, par habitude, annule le bénéfice serveur. Mettre "use client" sur le layout racine bascule toute l'app en client. Faire des appels base de données dans des composants client par confusion. Et oublier que le code serveur a accès aux variables d'environnement secrètes : il ne faut surtout pas les utiliser dans un Client Component, sous peine de les exposer publiquement. Les linters comme eslint-plugin-react-server-components attrapent une partie de ces erreurs avant le build.