Мир React долгое время делился на две «сферы»: серверный рендеринг (SSR) и клиентский рендеринг (CSR). Приложения обычно подгружали часть контента с сервера для быстрого старта, а затем загружали большой бандл JS для полного интерактивного опыта на клиенте. Однако это приводило к дублированию логики и дополнительной головной боли при оптимизации.
Сегодня громко обсуждаются React Server Components (RSC) — новый подход к рендерингу компонентов, при котором логика, которая не должна выполняться на клиенте, может быть полностью «вырезана» до отдачи готовой HTML-структуры. Это обещает уменьшить бандлы, улучшить производительность и упростить архитектуру.
Next.js 13 — фреймворк, который уже предлагает нативную поддержку RSC и новые возможности по маршрутизации, загрузке данных и оптимизации. Почему это важно и как начать?
Что такое React Server Components?
React Server Components — это компоненты, которые рендерятся только на сервере. Они:
Никогда не попадают на клиент: Код серверного компонента не загружается в браузер. В итоге уменьшается конечный размер бандла.
Могут использовать серверные API напрямую: Не нужно писать логику fetch на клиенте. Вы можете напрямую подключаться к базе данных или вызову к внешнему API на сервере, минуя лишние клиентские запросы.
Комбинируются с клиентскими компонентами: Если вам нужен интерактивный 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. Ведь это не просто ещё один хайп, а шаг вперёд в эволюции фронтенд-разработки.
guihal
Спасибо автору, заполнил несколько пробелов, которые у меня были, но сейчас уже 15 версия next...
guihal
И кстати, для производительности и минимизации кода можно юзать реактовский кеш на запросы, и потом спокойно их экспортировать в нужные компоненты.
Но не работает в том случае, если нужно получить что-то из гет запросов, тогда хуй в отдельный компонент выделишь(Или нет? Я это так и не попробовал, отмел сразу как идею)
DTGP Автор
Если рассматривать современный подход с RSC и React Cache, идея выделения GET-запроса в отдельный компонент полностью реализуема. Это не только работает, но и упрощает код, делая его более декларативным и предсказуемым. React Cache может работать с любыми асинхронными функциями, включая те, которые выполняют GET-запросы. Или что вы имели ввиду?
guihal
Я работал с next в payload cms, там доступ к гет параметрам возможен только из главного компонента страницы(pdge.tsx -> Page). А способа как получить нет параметры другим способом я не нашел. Конкретно я уже не помню проблему, но там была ошибка с тем, что что-то нельзя использовать с сервером компоненте