Join the discussion
Comments
Loading comments...
Cookie preferences
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Join the discussion
Loading comments...
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Frontière serveur/client, streaming du payload RSC et rendu serveur sans bundle.
Les Composants Serveur React (RSC) sont des composants qui s'exécutent exclusivement sur le serveur — ils ne sont jamais envoyés au navigateur. Ils peuvent accéder directement aux bases de données, systèmes de fichiers et secrets côté serveur sans aucun coût de bundle client. La sortie RSC n'est pas du HTML mais un format de transmission spécial (Payload RSC) que React côté client utilise pour reconstruire l'arbre de composants sans ré-exécuter le code serveur.
Lors du chargement d'une page, le serveur exécute vos Composants Serveur, effectuant directement des requêtes de base de données asynchrones, des lectures de fichiers ou des appels API. La sortie n'est pas du HTML — c'est un arbre d'éléments React sérialisé (le Payload RSC) dans un format de streaming personnalisé.
Lorsque le serveur rencontre un Composant Client (marqué avec 'use client'), il ne le rend pas. Au lieu de cela, il insère un placeholder CLIENT_REFERENCE dans le payload avec l'URL du module du composant et ses props. Le client remplit ces trous en exécutant le Composant Client dans le navigateur.
Le serveur diffuse le payload RSC au fur et à mesure qu'il complète chaque opération asynchrone. Le runtime React côté client reçoit des morceaux et construit progressivement l'arbre de composants — sortie des Composants Serveur d'abord, puis shells des Composants Client, puis hydratation.
React côté client prend le payload RSC diffusé et l'utilise pour reconstruire l'arbre complet de composants. Seuls les Composants Client sont hydratés (écouteurs d'événements attachés). La sortie des Composants Serveur est déjà finale — pas de ré-exécution côté client.
Les fonctions marquées avec 'use server' deviennent des Server Actions — des fonctions de style RPC que le client peut appeler comme des fonctions asynchrones normales. Sous le capot, React envoie une requête POST au serveur avec les arguments encodés et diffuse en retour le nouveau payload RSC.
Directive au niveau du fichier qui marque un module et tous ses imports comme Composants Client. Crée une frontière client — tous les exports peuvent utiliser des hooks, des gestionnaires d'événements et des APIs du navigateur.
Marque une fonction comme Server Action. Peut être appelée depuis des Composants Client via une requête réseau. La fonction s'exécute sur le serveur avec un accès complet côté serveur.
Un format JSON-like compact en streaming décrivant l'arbre de composants rendu côté serveur. Inclut des trous CLIENT_REFERENCE là où les composants client doivent aller. Pas du HTML.
Les Composants Serveur n'apparaissent jamais dans le bundle JS client. Un Composant Serveur qui importe un parseur markdown de 500Ko ajoute 0 octet au client.
Les composants sans 'use client' ni 'use server' peuvent être utilisés dans les deux contextes. Ils s'exécutent sur le serveur lorsqu'importés par un Composant Serveur, et sur le client lorsqu'importés par un Composant Client.
1// ServerComponent.tsx — runs ONLY on server2// No bundle cost, can use async/await, access DB directly3async function ProductPage({ id }) {4 const product = await db.products.findById(id); // direct DB access!56 return (7 <div>8 <h1>{product.name}</h1>9 {/* Pass server data to a client component */}10 <AddToCartButton productId={product.id} price={product.price} />11 </div>12 );13}1415// AddToCartButton.tsx — runs on client (needs onClick)16'use client';17function AddToCartButton({ productId, price }) {18 const [added, setAdded] = useState(false);1920 return (21 <button onClick={() => {22 addToCart(productId);23 setAdded(true);24 }}>25 {added ? 'Added!' : `Add for $${price}`}26 </button>27 );28}
Les Composants Serveur changent fondamentalement l'équation de performance. Auparavant, tout composant qui récupérait des données devait envoyer la bibliothèque de récupération, la logique de transformation de données et le code de rendu au client. Avec RSC, tout cela reste sur le serveur. Le client ne reçoit que la sortie rendue finale plus les îles interactives (Composants Client). Cela conduit à des bundles considérablement plus petits et un Time-to-Interactive plus rapide.
A product detail page needs to show: product info (from DB), reviews (from API), and an interactive 'Add to Cart' button. Traditional approach: fetch all data client-side with useEffect → loading spinners → hydration overhead.
Client-side fetching means: ship the fetch logic in the bundle → render loading state → make API calls from the browser → parse responses → re-render with data. The user sees a spinner, the bundle includes API client code, and there's a waterfall: page loads → JS executes → fetch starts → data arrives.
Make ProductPage and Reviews as Server Components (the default in Next.js App Router). They fetch data on the server with direct DB/API access and send pre-rendered HTML. Only AddToCartButton is a Client Component (marked with 'use client') because it needs onClick. Zero API client code in the bundle.
Takeaway: Server Components eliminate the request waterfall by moving data fetching to the server. Only interactive components (buttons, forms, animations) need to be Client Components. This pattern typically reduces bundle size by 30-50% and eliminates loading spinners for initial data.
You're building a blog post page. It has a header (static), article body (static with syntax-highlighted code), a comment section (interactive — like/reply buttons), and a share widget (interactive — copy link, social share).
New developers often mark the entire page as 'use client' because ONE component needs interactivity. This sends the entire page's JavaScript to the browser — syntax highlighting library, markdown parser, etc. — even though 80% of the page is static content.
Keep the page as a Server Component (default). Only wrap Comment and ShareWidget with 'use client'. The header, article body, and syntax highlighting render on the server and send zero JavaScript. The client only receives the small interactive components. Think of the boundary as: 'What needs browser APIs (state, effects, event handlers)?'
Takeaway: Push the 'use client' boundary as far DOWN the tree as possible. The rule: a component should be a Client Component only if it directly uses useState, useEffect, onClick, or browser-only APIs. Everything else should stay as a Server Component for zero bundle cost.