Мир React долгое время делился на две «сферы»: серверный рендеринг (SSR) и клиентский рендеринг (CSR). Приложения обычно подгружали часть контента с сервера для быстрого старта, а затем загружали большой бандл JS для полного интерактивного опыта на клиенте. Однако это приводило к дублированию логики и дополнительной головной боли при оптимизации.

Сегодня громко обсуждаются React Server Components (RSC) — новый подход к рендерингу компонентов, при котором логика, которая не должна выполняться на клиенте, может быть полностью «вырезана» до отдачи готовой HTML-структуры. Это обещает уменьшить бандлы, улучшить производительность и упростить архитектуру.

Next.js 13 — фреймворк, который уже предлагает нативную поддержку RSC и новые возможности по маршрутизации, загрузке данных и оптимизации. Почему это важно и как начать?

Что такое React Server Components?

React Server Components — это компоненты, которые рендерятся только на сервере. Они:

  1. Никогда не попадают на клиент: Код серверного компонента не загружается в браузер. В итоге уменьшается конечный размер бандла.

  2. Могут использовать серверные API напрямую: Не нужно писать логику fetch на клиенте. Вы можете напрямую подключаться к базе данных или вызову к внешнему API на сервере, минуя лишние клиентские запросы.

  3. Комбинируются с клиентскими компонентами: Если вам нужен интерактивный UI, часть приложения остаётся клиентской. Но всё, что не требует интерактивности (например, статический контент, данные, рассчитанные на сервере), остаётся на сервере.

Итог: быстрее загрузка страницы, меньше клиентского кода, удобнее организация данных.

Зачем нужен Next.js 13?

Next.js исторически стал стандартом для SSR в React. Версия 13 вводит новую структуру директорий (app/directory) и тесную интеграцию с React Server Components:

  • app router: Теперь маршрутизация и загрузка данных организованы более декларативно и чётко.

  • Легче работать с RSC: Можно объявлять компоненты как клиентские или серверные, используя специальные директивы ("use client"), и Next.js сам решит, как их рендерить.

  • Стандартные хуки и утилиты: Вы можете непосредственно запрашивать данные в серверных компонентах без необходимости «прокидывать» их через getStaticProps или getServerSideProps. Это упрощает код.

Пример структуры с RSC в Next.js 13

Представим структуру проекта:

app/
  page.jsx           // Серверный компонент для главной страницы
  dashboard/
    page.jsx         // Серверный компонент для страницы дашборда
  components/
    UserProfile.jsx  // Серверный или клиентский компонент

Допустим, UserProfile.jsx — компонент, который рендерит информацию о пользователе. Если он не требует интерактивного UI (нет кнопок с состоянием, нет useEffect), его можно сделать серверным. Тогда код может выглядеть так:

// app/components/UserProfile.jsx (серверный компонент)
export default async function UserProfile({ userId }) {
  const user = await getUserFromDB(userId); // прямой вызов к базе
  return (
    <div>
      <h2>{user.name}</h2>
      <p>Почта: {user.email}</p>
    </div>
  );
}

Нет fetch, нет отдельного API-роута для получения данных — всё сразу делается на сервере. Код этого компонента не попадёт в бандл клиента.

Если же вам нужен интерактивный компонент — например, кнопка, которая при клике меняет состояние и показывает/скрывает элемент — вы добавляете директиву "use client" в начале файла:

"use client";
import { useState } from "react";

export default function ToggleButton() {
  const [open, setOpen] = useState(false);
  return (
    <button onClick={() => setOpen(!open)}>
      {open ? "Скрыть" : "Показать"} панель
    </button>
  );
}

Этот код будет загружен на клиент и работать как привычный React-компонент.

Преимущества для производительности

  • Меньше JS на клиенте: Всё, что может быть выполнено на сервере, не превращается в клиентский код. Итог — меньше вес бандла, быстрая загрузка.

  • Упрощение логики данных: Нет необходимости писать двойную логику (одну для сервера, одну для клиента). Данные берутся прямо в серверных компонентах.

  • Быстрый Time-to-Interactive (TTI): Страница отдаётся уже в практически конечном виде, без длительных гидраций и ожиданий.

Подводные камни

  • Непривычный подход: Придётся изменить привычную архитектуру и понять, какие компоненты клиентские, а какие серверные.

  • Ограничения для серверных компонентов: Не все хуки React разрешены, нет состояния и жизненных циклов, потому что это просто рендер статичных данных. Но это не баг, а фича — уменьшение сложности.

  • Экосистема в процессе адаптации: Некоторые библиотеки могут ещё не быть оптимизированы для нового подхода. Со временем поддержка улучшится.

Стоит ли применять уже сейчас?

Next.js 13 и React Server Components уже достаточно стабильны, чтобы пробовать их в новых проектах. Если вы запускаете стартап или новый эксперимент, почему бы и нет? Вы получите производительный, чистый и современный подход к рендерингу.

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

React Server Components меняют парадигму SSR, делая её более естественной для React и избавляя от лишней сложности. В связке с Next.js 13 эта технология уже сегодня даёт возможность создавать быстрые, лёгкие и понятные приложения.

Если вы хотите идти в ногу с React-экосистемой, научиться эффективно работать с SSR и улучшить пользовательский опыт за счёт снижения нагрузки на клиент — самое время изучить React Server Components и Next.js 13. Ведь это не просто ещё один хайп, а шаг вперёд в эволюции фронтенд-разработки.

Комментарии (4)


  1. guihal
    10.12.2024 22:48

    Спасибо автору, заполнил несколько пробелов, которые у меня были, но сейчас уже 15 версия next...


    1. guihal
      10.12.2024 22:48

      И кстати, для производительности и минимизации кода можно юзать реактовский кеш на запросы, и потом спокойно их экспортировать в нужные компоненты.

      Но не работает в том случае, если нужно получить что-то из гет запросов, тогда хуй в отдельный компонент выделишь(Или нет? Я это так и не попробовал, отмел сразу как идею)


      1. DTGP Автор
        10.12.2024 22:48

        Если рассматривать современный подход с RSC и React Cache, идея выделения GET-запроса в отдельный компонент полностью реализуема. Это не только работает, но и упрощает код, делая его более декларативным и предсказуемым. React Cache может работать с любыми асинхронными функциями, включая те, которые выполняют GET-запросы. Или что вы имели ввиду?


        1. guihal
          10.12.2024 22:48

          Я работал с next в payload cms, там доступ к гет параметрам возможен только из главного компонента страницы(pdge.tsx -> Page). А способа как получить нет параметры другим способом я не нашел. Конкретно я уже не помню проблему, но там была ошибка с тем, что что-то нельзя использовать с сервером компоненте