React Server Components: практика для fullstack-разработчиков

#react#nextjs#performance

Когда в Next.js 13 появились Server Components, я отнёсся к ним скептически — ещё одна абстракция, которая усложнит жизнь. Но после нескольких месяцев работы с App Router понял: RSC (React Server Components) — это не просто модный термин, а реальный инструмент для решения конкретных проблем.

Server vs Client: где граница

Главный ментальный сдвиг: теперь у нас два типа компонентов с чёткими ограничениями:

// Server Component (по умолчанию)
async function UserProfile({ userId }) {
  const user = await db.users.findUnique({ where: { id: userId } });
  return <ProfileCard user={user} />;
}

// Client Component (явная пометка)
'use client';
function LikeButton() {
  const [likes, setLikes] = useState(0);
  return <button onClick={() => setLikes(l + 1)}>Likes: {likes}</button>;
}

На практике я выработал простое правило: если компонент не использует useState, useEffect или браузерные API (localStorage, window) — он должен быть Server Component. Особенно это касается:

Data fetching без боли

Раньше типичный сценарий выглядел так:

  1. Рендерим скелетон
  2. Летит запрос на API роут
  3. Получаем данные
  4. Обновляем UI

С RSC схема упрощается до:

// Раньше
function Page() {
  const [data, setData] = useState(null);
  useEffect(() => {
    fetch('/api/posts').then(r => r.json()).then(setData);
  }, []);
  return data ? <Posts posts={data} /> : <Loader />;
}

// Теперь
async function Page() {
  const posts = await db.posts.findMany();
  return <Posts posts={posts} />;
}

Но есть нюанс: нельзя просто взять и заменить все useEffect на прямые запросы к БД. Важно учитывать:

Постепенная миграция

Главный страх при внедрении RSC — необходимость переписывать весь проект. На практике я рекомендую такой подход:

  1. Новые страницы — сразу делаем на App Router
  2. Критические пути (например, главная) — оставляем в Pages Router, пока не протестируем RSC
  3. Изолированные фичи — переводим по одной, начиная с самых “тяжёлых”

Пример гибридного роутинга в Next.js:

/app
  /dashboard  # Новый RSC-роут
/pages
  /index.tsx  # Старая страница

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

После полугода работы с RSC я собрал список неочевидных проблем:

  1. Интеграция с внешними библиотеками
    Многие UI-киты пока не адаптированы под Server Components. Например, попытка использовать useClient внутри библиотечного компонента может сломать сборку.

  2. Отладка
    Ошибки в Server Components иногда дают малопонятные stack traces. Приходится включать NEXT_VERBOSE=1 и копать логи сервера.

  3. Кеширование
    По умолчанию Next.js агрессивно кеширует RSC. Это хорошо для перфоманса, но может сбивать с толку при разработке. Решение — явно настраивать fetchOptions.cache.

RSC — не серебряная пуля. Для SPA-подобных приложений с богатой клиентской логикой они могут добавить сложности без явных выгод. Но для content-heavy сайтов (блоги, маркетплейсы, медиа) — это реальный способ сократить TTI (Time To Interactive) на 20-40%.

Что попробовать дальше:


Источник: https://dev.to/therizwansaleem/react-server-components-a-practical-guide-for-fullstack-developers-26od