Серверные компоненты (Server Components)

Серверные компоненты React позволяют создавать интерфейсы, которые могут быть отрендерены и при необходимости закэшированы на сервере. В Next.js работа по рендерингу дополнительно разделяется по сегментам маршрутов для поддержки потоковой передачи и частичного рендеринга, доступны три стратегии серверного рендеринга:

На этой странице объясняется, как работают серверные компоненты, когда их стоит использовать, и различные стратегии серверного рендеринга.

Преимущества серверного рендеринга

Рендеринг на сервере имеет несколько преимуществ:

  • Загрузка данных: Серверные компоненты позволяют перенести загрузку данных ближе к их источнику. Это улучшает производительность, сокращая время загрузки данных и количество запросов со стороны клиента.
  • Безопасность: Серверные компоненты позволяют хранить конфиденциальные данные и логику (например, токены и API-ключи) на сервере, исключая риск их утечки клиенту.
  • Кэширование: Результаты рендеринга на сервере могут быть закэшированы и повторно использованы для последующих запросов и между пользователями. Это улучшает производительность и снижает затраты за счет уменьшения объема рендеринга и загрузки данных для каждого запроса.
  • Размер бандла: Серверные компоненты позволяют оставлять большие зависимости на сервере, которые раньше увеличивали размер клиентского JavaScript-бандла. Это особенно полезно для пользователей с медленным интернетом или слабыми устройствами, так как клиенту не нужно загружать, парсить и выполнять JavaScript для серверных компонентов.
  • Первоначальная загрузка страницы и First Contentful Paint (FCP): На сервере можно генерировать HTML, позволяя пользователям сразу видеть страницу без ожидания загрузки, парсинга и выполнения JavaScript на клиенте.
  • SEO и шаринг в соцсетях: Сгенерированный HTML используется поисковыми ботами для индексации страниц и ботами соцсетей для создания превью.
  • Потоковая передача: Серверные компоненты позволяют разбить рендеринг на части и передавать их клиенту по мере готовности. Это позволяет пользователю видеть части страницы раньше, не дожидаясь полного рендеринга.

Использование серверных компонентов в Next.js

По умолчанию Next.js использует серверные компоненты. Это позволяет автоматически реализовать серверный рендеринг без дополнительной настройки. При необходимости можно использовать клиентские компоненты.

Как рендерятся серверные компоненты?

На сервере Next.js использует API React для организации рендеринга. Работа разделяется на части: по отдельным сегментам маршрутов и границам Suspense.

Каждая часть рендерится в два этапа:

  1. React рендерит серверные компоненты в специальном формате данных — React Server Component Payload (RSC Payload).
  2. Next.js использует RSC Payload и инструкции JavaScript клиентских компонентов для рендеринга HTML на сервере.

Затем на клиенте:

  1. HTML используется для мгновенного показа быстрого неинтерактивного превью страницы (только при первоначальной загрузке).
  2. RSC Payload используется для согласования деревьев клиентских и серверных компонентов и обновления DOM.
  3. JavaScript-инструкции используются для гидратации клиентских компонентов и обеспечения интерактивности приложения.

Что такое React Server Component Payload (RSC)?

RSC Payload — это компактное бинарное представление дерева отрендеренных серверных компонентов React. Оно используется React на клиенте для обновления DOM. RSC Payload содержит:

  • Результат рендеринга серверных компонентов
  • Заполнители для клиентских компонентов и ссылки на их JavaScript-файлы
  • Пропсы, переданные от серверных компонентов к клиентским

Стратегии серверного рендеринга

Существует три подхода к серверному рендерингу: статический, динамический и потоковая передача.

Статический рендеринг (по умолчанию)

При статическом рендеринге маршруты рендерятся во время сборки или в фоне после ревалидации данных. Результат кэшируется и может быть размещен в CDN. Это позволяет повторно использовать результаты рендеринга между пользователями и запросами.

Статический рендеринг полезен, когда данные маршрута не персонализированы и известны во время сборки, например, для статической статьи блога или страницы товара.

Динамический рендеринг

При динамическом рендеринге маршруты рендерятся для каждого пользователя во время запроса.

Динамический рендеринг полезен, когда данные персонализированы или зависят от информации, доступной только во время запроса, например, cookies или параметров URL.

Динамические маршруты с кэшированными данными

В большинстве сайтов маршруты не являются полностью статическими или динамическими — это спектр. Например, страница интернет-магазина может использовать кэшированные данные товаров с периодической ревалидацией, но также содержать некэшированные персональные данные пользователя.

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

Подробнее о кэше всего маршрута и кэше данных.

Переключение на динамический рендеринг

Если во время рендеринга обнаруживается динамическая функция или некэшированный запрос данных, Next.js переключается на динамический рендеринг всего маршрута. В таблице ниже показано, как динамические функции и кэширование данных влияют на стратегию рендеринга:

Динамические функцииДанныеМаршрут
НетКэшированыСтатический рендеринг
ДаКэшированыДинамический рендеринг
НетНе кэшированыДинамический рендеринг
ДаНе кэшированыДинамический рендеринг

Для полностью статического маршрута все данные должны быть кэшированы. Однако можно иметь динамически рендерящийся маршрут с сочетанием кэшированных и некэшированных данных.

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

Динамические функции

Динамические функции зависят от информации, доступной только во время запроса (cookies, заголовки, параметры URL). В Next.js к ним относятся:

  • cookies() и headers(): Их использование в серверном компоненте переводит весь маршрут в динамический рендеринг.
  • useSearchParams():
    • В клиентских компонентах пропускает статический рендеринг, рендеря все клиентские компоненты до ближайшей границы Suspense на клиенте.
    • Рекомендуется оборачивать клиентский компонент с useSearchParams() в <Suspense/>, чтобы вышележащие компоненты рендерились статически. Пример.
  • searchParams: Использование этого пропа в страницах переводит страницу в динамический рендеринг.

Использование этих функций переводит весь маршрут в динамический рендеринг.

Потоковая передача

Диаграмма параллельной обработки сегментов маршрута при потоковой передаче, показывающая загрузку данных, рендеринг и гидратацию отдельных частей.

Потоковая передача позволяет постепенно рендерить интерфейс на сервере. Работа разбивается на части и передается клиенту по мере готовности. Это позволяет пользователю видеть части страницы сразу, не дожидаясь полного рендеринга.

Диаграмма частично отрендеренной страницы на клиенте с индикаторами загрузки для потоково передаваемых частей.

Потоковая передача встроена в App Router Next.js по умолчанию. Это улучшает как первоначальную загрузку, так и отображение интерфейсов, зависящих от медленных запросов данных. Например, отзывы на странице товара.

Потоковую передачу можно настроить с помощью loading.js и компонентов с React Suspense. Подробнее в разделе Интерфейс загрузки и потоковая передача.