Що таке React Server Components (RSC)?
1. Що таке React Server Components (RSC)
React Server Components (RSC) - це компоненти, які виконуються на сервері, а не в браузері, і при цьому інтегруються в одне дерево React із клієнтськими компонентами.
Простіше кажучи:
RSC - це спосіб рендерити частину React-застосунку на сервері, але при цьому залишати решту частини інтерактивною на клієнті, без дублювання логіки чи SSR-гідратації всього дерева.
2. Чим RSC відрізняються від SSR
| Критерій | SSR (Server-Side Rendering) | RSC (React Server Components) |
|---|---|---|
| Де виконується | Сервер генерує HTML | Сервер генерує React-структуру (дерево) |
| Що надсилається клієнту | Готовий HTML | Потік серіалізованих компонентів |
| Що робить клієнт | «Оживляє» HTML (hydration) | Об'єднує серверні та клієнтські компоненти |
| Коли виконується | За кожного запиту | Може бути під час білда, фетчу або частково |
| Де можна писати fetch | Зазвичай у getServerSideProps | Прямо всередині компонента! |
Тобто SSR = «рендер HTML на сервері», а RSC = «рендер React-компонентів на сервері без HTML».
3. Як працює механізм RSC
Крок 1. Поділ на типи компонентів
RSC вводить два типи компонентів:
| Тип | Де виконується | Чи можна використовувати Hooks / DOM |
|---|---|---|
| Server Component | Лише на сервері | Не можна useState, useEffect, window, document |
| Client Component | У браузері | Можна все (хуки, DOM, події тощо) |
Позначення в коді:
// This is a server component (the default)
export default async function Page() {
const data = await fetch('https://api.example.com/posts').then(r => r.json());
return <PostList posts={data} />;
}
// This is a client component
"use client";
import { useState } from "react";
export function LikeButton() {
const [liked, setLiked] = useState(false);
return <button onClick={() => setLiked(!liked)}>{liked ? "Liked" : "Not liked"}</button>;
}Крок 2. Серверний рендер повертає не HTML, а React Payload
React Server Components не надсилають HTML. Сервер генерує потік серіалізованих React-компонентів, який називається React Flight Data.
Приклад (спрощено):
[
["$","div",null,{"children":["Hello from server"]}],
["$","button","client:likeButton",{"children":["Liked"]}]
]Клієнт отримує цей «JSON-потік» і збирає дерево React за допомогою RSC runtime.
Тобто на клієнт приходить не HTML, а «інструкції» для React про те, які компоненти відрисувати і які з них клієнтські.
Крок 3. Об'єднання (гібридне дерево)
На клієнті React об'єднує два світи:
- Серверні компоненти - відрисовані заздалегідь (їхнього JS-коду навіть немає на клієнті),
- Клієнтські компоненти - завантажуються, гідруються і стають інтерактивними.
<App>
├── <Header /> → Server Component
├── <PostList /> → Server Component
│ ├── <Post /> → Server Component
│ └── <LikeButton /> → Client Component
└── <Footer /> → Server ComponentТаким чином, клієнт отримує мінімальний JS - лише для LikeButton. Все інше вже відрендерено на сервері й не потребує гідратації.
4. Переваги RSC
| Перевага | Чому це круто |
|---|---|
| Менше JS на клієнті | Клієнту взагалі не потрібен код серверних компонентів |
| Немає подвійного рендера (як за SSR) | RSC не потребує гідратації HTML, немає дублювання |
| Гібридність | Можна змішувати серверні та клієнтські компоненти в одному дереві |
| Безпека | Серверні компоненти не потрапляють на клієнт, не можна випадково «злити» ключі чи API-токени |
| Швидший рендер великих списків / даних | Логіка та запити виконуються на сервері, а не в браузері |
| Сумісність зі Streaming SSR | Можна стрімити серверні та клієнтські частини асинхронно |
5. Приклад RSC у Next.js 13+ (App Router)
// app/page.tsx - Server Component (the default)
import Posts from './Posts';
export default async function Page() {
const posts = await fetch('https://jsonplaceholder.typicode.com/posts').then(r => r.json());
return (
<main>
<h1>Server-rendered posts</h1>
<Posts posts={posts} />
</main>
);
}// app/Posts.tsx - Server Component
import LikeButton from './LikeButton';
export default function Posts({ posts }) {
return (
<ul>
{posts.map(p => (
<li key={p.id}>
{p.title} <LikeButton />
</li>
))}
</ul>
);
}// app/LikeButton.tsx - Client Component
"use client";
import { useState } from "react";
export default function LikeButton() {
const [liked, setLiked] = useState(false);
return (
<button onClick={() => setLiked(!liked)}>
{liked ? "Liked" : "Not liked"}
</button>
);
}Весь список постів рендериться на сервері, а кнопка «лайк» - інтерактивна, але завантажується окремим JS-чанком.
6. RSC ≠ SSR
| Відмінність | SSR | RSC |
|---|---|---|
| Формат виводу | HTML | React Payload (інструкції) |
| Гідратація | Обов'язкова | Не потрібна |
| Де зберігається логіка даних | У «getServerSideProps» / API | Прямо в компонентах |
| Чи можна змішувати з клієнтськими компонентами | Обмежено | Так, гібридно |
| Продуктивність | Вища, ніж CSR, але потребує подвійного рендера | Ще вища - менше JS і менше HTML |
Підсумок
React Server Components (RSC) - це новий фундамент React, який:
- переносить частину логіки та рендерингу на сервер,
- залишає інтерактивність клієнту,
- прибирає потребу в «hydration» для статичних частин,
- зменшує розмір JS і пришвидшує завантаження сторінок,
- і дає змогу змішувати серверний і клієнтський код в одному дереві.
Якщо SSR = «сервер генерує HTML», то RSC = «сервер генерує React-дерево». І це наближає React до universal rendering - розумної, гібридної моделі, де кожен компонент виконується там, де це вигідніше.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.