TL;DR
React Server Components (RSC) to komponenty renderowane po stronie serwera, które nie wysyłają JavaScript do przeglądarki. Zmniejszają rozmiar bundle'a, poprawiają wydajność i SEO. Oto jak działają i kiedy ich używać w 2026.
Dla kogo to jest
- Deweloperów React/Next.js chcących poprawić wydajność
- Zespołów budujących aplikacje z dużą ilością danych
- Firm szukających lepszego SEO i szybkości ładowania
Fraza (SEO)
react server components, rsc, nextjs server components, react performance, server-side rendering
Czym są React Server Components?
React Server Components to:
- Komponenty renderowane tylko na serwerze
- Zero JavaScript wysyłany do przeglądarki
- Bezpośredni dostęp do baz danych i API
- Mniejsze bundle'y i szybsze ładowanie
Główne różnice:
| Server Components | Client Components |
|---|---|
| Render na serwerze | Render w przeglądarce |
| Brak JavaScript | JavaScript w bundle |
| Dostęp do DB/API | Tylko fetch |
| Brak interaktywności | Pełna interaktywność |
Jak działają Server Components?
1. Renderowanie na serwerze
Server Component:
// app/products/page.tsx
async function ProductsPage() {
// Bezpośredni dostęp do DB
const products = await db.products.findMany();
return (
<div>
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
Co się dzieje:
- Serwer renderuje komponent
- Wysyła HTML do przeglądarki
- Zero JavaScript dla tego komponentu
2. Client Components dla interaktywności
Gdy potrzebujesz interaktywności:
'use client'; // Dyrektywa dla Client Component
import { useState } from 'react';
export function AddToCartButton({ productId }: { productId: number }) {
const [loading, setLoading] = useState(false);
const handleClick = async () => {
setLoading(true);
await addToCart(productId);
setLoading(false);
};
return (
<button onClick={handleClick} disabled={loading}>
Dodaj do koszyka
</button>
);
}
Korzyści Server Components
1. Mniejszy bundle JavaScript
Przed RSC:
- Wszystkie komponenty w bundle
- Duży rozmiar (500KB+)
- Wolne ładowanie
Z RSC:
- Tylko Client Components w bundle
- Mniejszy rozmiar (50-100KB)
- Szybsze ładowanie
2. Bezpośredni dostęp do danych
Bez RSC:
'use client';
useEffect(() => {
fetch('/api/products')
.then(res => res.json())
.then(setProducts);
}, []);
Z RSC:
async function ProductsPage() {
const products = await db.products.findMany();
// Brak fetch, brak useEffect
return <ProductList products={products} />;
}
3. Lepsze SEO
- Pełny HTML od razu w odpowiedzi
- Brak JavaScript wymagany do renderowania
- Szybsze indeksowanie przez Google
4. Bezpieczeństwo
Sekretne klucze API:
// Server Component - bezpieczne
async function PaymentPage() {
const apiKey = process.env.STRIPE_SECRET_KEY; // ✅ Bezpieczne
// ...
}
// Client Component - NIEBEZPIECZNE
'use client';
const apiKey = process.env.STRIPE_SECRET_KEY; // ❌ Widoczne w bundle!
Kiedy używać Server Components?
✅ Używaj Server Components dla:
Wyświetlania danych
- Listy produktów
- Blog posts
- Statystyki
- Tabele danych
Statycznych sekcji
- Header/Footer
- Nawigacja
- Sidebar
- SEO metadata
Dostęp do baz danych
- Prisma queries
- SQL queries
- API calls z sekretami
❌ Używaj Client Components dla:
Interaktywności
- Formularze
- Przyciski
- Dropdowny
- Modale
Hooks React
- useState
- useEffect
- useContext
- useReducer
Event handlers
- onClick
- onChange
- onSubmit
Next.js 13+ App Router
Struktura:
app/
layout.tsx # Server Component (domyślnie)
page.tsx # Server Component
products/
page.tsx # Server Component
[id]/
page.tsx # Server Component
components/
Button.tsx # Client Component ('use client')
Przykład:
// app/products/page.tsx (Server Component)
import { db } from '@/lib/db';
import { ProductCard } from '@/components/ProductCard';
import { AddToCartButton } from '@/components/AddToCartButton';
export default async function ProductsPage() {
const products = await db.products.findMany();
return (
<div>
<h1>Produkty</h1>
{products.map(product => (
<div key={product.id}>
<ProductCard product={product} />
<AddToCartButton productId={product.id} />
</div>
))}
</div>
);
}
Best Practices
1. Domyślnie Server Components
Zasada: Wszystko jest Server Component, chyba że potrzebujesz interaktywności.
// ✅ Server Component (domyślnie)
export function ProductList({ products }: { products: Product[] }) {
return (
<div>
{products.map(p => <ProductCard key={p.id} product={p} />)}
</div>
);
}
2. Minimalizuj Client Components
Zamiast:
'use client';
export function ProductPage() {
const [products, setProducts] = useState([]);
// ...
}
Lepiej:
// Server Component
export default async function ProductPage() {
const products = await getProducts();
return <ProductList products={products} />;
}
3. Kompozycja Server + Client
Wzorzec:
// Server Component
export default async function Page() {
const data = await fetchData();
return <InteractiveComponent data={data} />;
}
// Client Component
'use client';
export function InteractiveComponent({ data }: { data: Data }) {
const [state, setState] = useState();
// Interaktywność z danymi z serwera
}
4. Streaming i Suspense
Loading states:
import { Suspense } from 'react';
export default function Page() {
return (
<div>
<Suspense fallback={<Skeleton />}>
<ProductsList />
</Suspense>
</div>
);
}
FAQ
Czy Server Components zastępują SSR?
Nie, uzupełniają się. SSR renderuje HTML na serwerze, ale nadal wysyła JavaScript. RSC nie wysyłają JavaScript dla komponentów serwerowych.
Czy mogę używać hooks w Server Components?
Nie. Server Components nie mogą używać hooks React (useState, useEffect, etc.). Tylko Client Components.
Jak przekazać dane z Server do Client Component?
Przez props:
// Server Component
const data = await fetchData();
return <ClientComponent data={data} />;
Czy Server Components są szybsze?
Tak, bo:
- Mniejszy bundle JavaScript
- Brak hydratacji dla Server Components
- Szybsze pierwsze renderowanie