Перейти к содержанию
Innovialabs

React Server Components: как они работают и зачем нужны

Продвинутое3 мин

Коротко

Server Components выполняются только на сервере и не попадают в JavaScript-бандл браузера; интерактивные части выносятся в Client Components с "use client", а между ними передаются только сериализуемые данные.

Что такое Server Components

React Server Components (RSC) — компоненты, которые выполняются только на сервере. Их код не отправляется в браузер: клиент получает уже готовый результат рендеринга в специальном формате, а React встраивает его в страницу.

Что это даёт:

  • меньше JavaScript в браузере — тяжёлые библиотеки (парсер Markdown, форматирование дат, SDK базы данных) остаются на сервере;
  • данные рядом с источником — компонент может напрямую обратиться к базе или внутреннему API;
  • секреты в безопасности — ключи и токены не попадают в клиентский бандл.

Важно: RSC — это не то же самое, что классический SSR. SSR превращает компоненты в HTML для первого показа, но потом весь их код всё равно загружается в браузер. Server Components в браузер не загружаются вовсе.

Граница сервер/клиент и "use client"

В фреймворках с поддержкой RSC (например, App Router в Next.js) компоненты по умолчанию серверные. Чтобы сделать компонент клиентским, в начале файла ставят директиву:

"use client";

import { useState } from "react";

export function LikeButton() {
  const [liked, setLiked] = useState(false);
  return <button onClick={() => setLiked(!liked)}>{liked ? "♥" : "♡"}</button>;
}

Ключевые правила:

  • "use client" отмечает точку входа на клиент: этот файл и всё, что он импортирует, попадает в бандл.
  • Клиентским компонентам доступны состояние, эффекты, обработчики событий и браузерные API.
  • Серверный компонент может рендерить клиентский. Обратное — импортировать серверный компонент внутрь клиентского — нельзя.
  • Но серверный компонент можно передать в клиентский через children или другой prop:
// серверный компонент
<Tabs>
  <ProductDescription id={id} />
</Tabs>

Здесь Tabs — клиентский, а ProductDescription остаётся серверным.

Правила сериализации

Всё, что серверный компонент передаёт клиентскому через props, должно быть сериализуемым.

Можно передаватьНельзя передавать
строки, числа, boolean, nullобычные функции и обработчики
простые объекты и массивыэкземпляры классов
Date, Map, Setсимволы, созданные не через Symbol.for
JSX (серверные компоненты как children)объекты с циклическими ссылками
Promiseсоединения с БД, сокеты
Server Actions (функции с "use server")

Частая ошибка — передать onClick из серверного компонента. Решение: перенести обработчик внутрь клиентского компонента или использовать Server Action.

Загрузка данных

Серверный компонент может быть асинхронным:

export default async function OrdersPage() {
  const orders = await db.order.findMany({ take: 20 });
  return <OrdersTable orders={orders} />;
}

Практические паттерны:

  • Загружайте данные там, где они нужны, а не в одном корневом компоненте. Одинаковые запросы в рамках рендера можно дедуплицировать через cache из React.
  • Запускайте независимые запросы параллельно через Promise.all, иначе получите «водопад» из последовательных ожиданий.
  • Используйте Suspense, чтобы медленная часть не блокировала всю страницу: быстрые блоки покажутся сразу, медленные — по мере готовности.
  • Для изменения данных — Server Actions, а не fetch к собственному API.

Типичные ошибки

  • "use client" в корневом лейауте. Всё дерево становится клиентским, и выгода RSC пропадает. Держите клиентские компоненты маленькими и на «листьях».
  • Импорт серверного кода в клиентский файл. Библиотека для БД попадёт в бандл или сборка упадёт. Пакет server-only помогает поймать это на этапе сборки.
  • Ожидание, что серверный компонент перерендерится от клика. Он рендерится по запросу, а не от состояния в браузере. Для обновления нужна навигация, router.refresh() или ревалидация.
  • Передача лишних данных в props. Всё, что уходит в клиентский компонент, видно в ответе сервера. Не отдавайте целые записи из базы с внутренними полями.
  • Использование контекста в серверных компонентах. createContext и провайдеры работают только на клиенте.

Частые вопросы

RSC требуют поддержки со стороны сборщика и сервера, поэтому на практике их используют через фреймворк. Next.js — самый распространённый вариант, но поддержка появляется и в других инструментах.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.