Ce sunt React Server Components?
React Server Components (RSC) reprezintă o paradigmă fundamental nouă în arhitectura aplicațiilor React. Spre deosebire de componentele tradiționale care se execută exclusiv în browser, componentele de server se execută integral pe server, iar rezultatul — un flux de date serializat — este trimis clientului.
În esență, RSC permite Reactului să „gândească" pe server și să trimită un RSC payload — un format binar compact pe care clientul îl poate hidrata fără a re-exeeca codul componentelor. Acest mecanism combină cele mai bune părți dintre rendering-ul tradițional pe server (SSR) și interactivitatea SPA-urilor.
Cum funcționează streaming-ul
RSC introduce conceptul de streaming: serverul trimite porțiuni de UI pe măsură ce sunt gata, nu așteaptă să se compileze totul. În combinație cu <Suspense>, poți afișa instant un skeleton de încărcare și să înlocuiești porțiunile de conținut pe măsură ce datele sosesc de la server.
// Server Component - se execută pe server
async function UserProfile({ userId }) {
const user = await db.user.findUnique({ where: { id: userId } });
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
{/* Această componentă client se încarcă ulterior */}
<Suspense fallback={<Skeleton />}>
<UserActivity userId={userId} />
</Suspense>
</div>
);
}
Cum funcționează RSC sub capotă
Arhitectura RSC se bazează pe o separare clară între două tipuri de componente:
- Componente de server — se execută doar pe server, nu au acces la state, event handleri sau hook-uri de React. Pot folosi direct API-uri de server (baze de date, sistem de fișiere, etc.) fără a crea endpoint-uri separate.
- Componente de client — marcate cu
'use client'în fișier, se execută în browser și suportă interactivitate completă.
Când un client navighează la o pagină, serverul compilează arborele de componente, execută componentele de server, serializează rezultatul în RSC payload și îl trimite prin HTTP. Clientul primește acest payload, combină componentele client existente (hidratate) cu cele primite de la server, și construiește UI-ul final.
Componente de Server vs. Componente de Client: Când să folosești fiecare
Folosește componente de server când:
- Ai nevoie de acces direct la date (baze de date, CMS, API-uri interne)
- Componenta este exclusiv de prezentare (nu are interactivitate)
- Vrei să elimini bundle-ul de JavaScript al componentei
- Lucrezi cu componente care necesită dependențe heavy (de exemplu, biblioteci de parsing markdown)
Folosește componente de client când:
- Componenta are event handleri (
onClick,onChange, etc.) - Folosește state local (
useState,useReducer) - Folosește efecte secundare (
useEffect,useCallback) - Depinde de API-uri de browser (localStorage, WebSocket, IntersectionObserver)
// Componentă de server - zero JavaScript trimis clientului
async function ProductList() {
const products = await db.product.findMany();
return (
<ul>
{products.map(p => (
<li key={p.id}>{p.name} - {p.price} EUR</li>
))}
</ul>
);
}
// Componentă de client - cu interactivitate
'use client';
import { useState } from 'react';
function AddToCartButton({ productId }) {
const [loading, setLoading] = useState(false);
return (
<button
onClick={async () => {
setLoading(true);
await fetch('/api/cart', {
method: 'POST',
body: JSON.stringify({ productId })
});
setLoading(false);
}}
>
{loading ? 'Se adaugă...' : 'Adaugă în coș'}
</button>
);
}
Câștiguri Reale de Performanță
Datele din producție sunt clare: adoptarea RSC aduce îmbunătățiri semnificative:
- Reducere de 40–60% a volumului de JavaScript trimis clientului — componentele de server nu contribuie la bundle size
- Îmbunătățirea LCP (Largest Contentful Paint) — conținutul text este disponibil mai rapid datorită streaming-ului
- TTFB cu 30% mai rapid — serverul începe să trimită date înainte ca întreaga pagină să fie compilată
- Reducerea Time to Interactive — mai puțin JavaScript înseamnă browserul trebuie să parseze și să execute mai puțin cod
Streaming + Suspense: Combinația Perfectă
Cel mai puternic pattern în RSC este combinarea streaming-ului cu React Suspense. În loc să aștepte ca toate datele să sosească, serverul trimite porțiunile de UI care sunt gata și înfășoară restul în boundary-uri de Suspense.
import { Suspense } from 'react';
export default function DashboardPage() {
return (
<div>
{/* Acest header se încarcă instant */}
<Header />
{/* Conținutul se streaminguiezează pe rând */}
<Suspense fallback={<ChartSkeleton />}>
<AnalyticsChart />
</Suspense>
<Suspense fallback={<TableSkeleton />}>
<RecentOrders />
</Suspense>
<Suspense fallback={<CardSkeleton />}>
<UserStats />
</Suspense>
</div>
);
}
Rezultatul? Utilizatorul vede header-ul instant, apoi conținutul apare pe rând pe măsură ce devine disponibil, fără flash-uri de conținut sau layout shifts.
Anti-patternuri Comune în RSC
Chiar dacă RSC este puternic, există capcane în care cade multă lume:
- Client-izare excesivă — nu marca o componentă cu
'use client'dacă nu are nevoie de interactivitate. Multe componente pur de prezentare pot rămâne pe server. - Pasarea datelor de la server la client prin props — evită să treci obiecte mari prin props între server și client. Folosește server actions sau API routes pentru mutarea datelor.
- Ignorarea granularității — pune
'use client'pe cea mai mică componentă posibilă, nu pe întregul fișier. Dacă doar butonul are nevoie de interactivitate, marchează doar butonul. - Suprasolicitarea efectelor secundare — în loc de
useEffectpentru fetch-ul de date, preferă server components care fac direct query-ul.
Strategia de Migrație pentru Proiecte Existente
Migrarea la RSC nu trebuie să fie „big bang". Iată pașii recomandați:
- Începe cu Next.js App Router — dacă folosești deja Next.js, migrează gradual la App Router. Nu trebuie să migrezi toate paginile simultan.
- Identifică componentele care nu au interactivitate — acestea sunt candidatul perfect pentru componentele de server. Layout-uri, headers, footers, liste de conținut.
- Mută logica de date pe server — în loc de
useEffect+ fetch, folosește server components cu async/await direct. - Păstrează 'use client' pentru componentele cu interactivitate — form-uri, butoane, modale, navigație.
- Testează performanța — măsoară bundle size, LCP, TTFB înainte și după migrare.
FAQ
RSC înlocuiește API routes?
Nu complet. RSC îți permite să accesezi direct datele din componente, dar API routes rămân utile pentru webhook-uri, endpoint-uri publice, și orice necesită răspunsuri non-HTML (JSON, fișiere).
Cum gestionez state-ul cu RSC?
State-ul local rămâne în componentele de client (useState, useReducer). Pentru state global, poți folosi în continuare Context, Zustand sau Jotai — toate funcționează normal în componentele de client.
Are impact asupra SEO?
Dimpotrivă — RSC îmbunătățește SEO. Conținutul server-rendered este disponibil instant pentru crawleri, iar streaming-ul nu afectează indexarea deoarece crawler-ul primește HTML complet.