Серверные компоненты по умолчанию

Самое важное в Next.js: почему ваши компоненты по умолчанию выполняются на сервере, а не в браузере.

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

Поворот в мышлении

В обычном React весь код едет в браузер и выполняется там. В App Router всё наоборот: по умолчанию компонент серверный. Он выполняется на сервере один раз, превращается в готовый HTML, и этот HTML отправляется клиенту. Сам код компонента в браузер не уезжает.

Что это даёт на практике:

  • Меньше JavaScript в браузере — быстрее загрузка и интерактивность.
  • Прямой доступ к данным — можно обращаться к БД и файловой системе без отдельного API.
  • Безопасность секретов — ключи и токены остаются на сервере, в браузер не попадают.

Как выглядит серверный компонент

Внешне — это обычный компонент. Особенность: он может быть async и грузить данные прямо в теле. Этот код выполнится на сервере:

// app/page.tsx — серверный компонент (по умолчанию)
import { db } from "@/lib/db";

export default async function HomePage() {
  const posts = await db.posts.findMany(); // прямой доступ к БД на сервере
  return (
    <ul>
      {posts.map((p) => (
        <li key={p.id}>{p.title}</li>
      ))}
    </ul>
  );
}

Здесь блок помечен language-text, потому что обращение к БД работает только на сервере — «пощупать» в браузере его нельзя. Но идея ясна: данные читаются прямо в компоненте.

Чего серверный компонент НЕ умеет

Раз код не уезжает в браузер, в серверном компоненте нельзя использовать то, что живёт в браузере:

Нельзя в серверном компонентеПочему
useState, useEffectЭто состояние и эффекты браузера
onClick и другие обработчикиИнтерактивность — это клиент
window, localStorageСуществуют только в браузере

Для всего интерактивного есть клиентские компоненты — о них следующий урок.

Прикинем экономию

Допустим, библиотека форматирования дат весит 30 КБ. Если она нужна только на сервере для подготовки строки, в браузер она не поедет:

const libraryKb = 30;
const componentsUsingOnServer = 8;
const saved = libraryKb; // грузим один раз на сервере, в бандл не кладём
console.log("Сэкономлено в браузерном бандле, КБ:", saved);
console.log("HTML с готовыми датами всё равно доедет до пользователя");

Вывод:

Сэкономлено в браузерном бандле, КБ: 30
HTML с готовыми датами всё равно доедет до пользователя

Итог

  • В App Router компоненты по умолчанию серверные — их JS не уезжает в браузер.
  • Серверный компонент может быть async и напрямую читать данные и секреты.
  • В нём нельзя использовать состояние, эффекты, обработчики и window.
Проверьте себя
1. Где выполняется серверный компонент в App Router?
AВ браузере пользователя
BНа сервере; в браузер уезжает готовый HTML, а не код компонента
CСначала на сервере, потом полностью повторно в браузере
DТолько во время сборки
2. Что НЕЛЬЗЯ использовать внутри серверного компонента?
Aasync/await
BОбращение к базе данных
CuseState, useEffect и onClick
DИмпорт других компонентов
3. Почему серверные компоненты уменьшают размер браузерного бандла?
AОни сжимают JavaScript
BИх код выполняется на сервере и не отправляется в браузер
CОни отключают React
DОни кэшируют весь сайт
Поддержать проект