Веб-разработка

SSR и SSG: Next.js, Nuxt

SPA: пользователь видит белый экран 2-3 секунды пока грузится JS, потом ещё 1-2 секунды пока приходят данные. Поисковик видит пустую страницу. Next.js с RSC и Streaming SSR: HTML приходит за 50мс, данные стримятся по мере готовности, JS бандл минимален. Это не оптимизация - это принципиально другая модель.

  • **Shopify** перешёл на RSC для своих storefront - сокращение JS бандла на 35%, LCP улучшился на 40%
  • **Vercel** - компания стоящая за Next.js - строит весь свой дашборд на RSC + Streaming SSR
  • **GitHub** использует Turbo Frames (похожий паттерн) для частичной загрузки страниц без полного reload

React Server Components

До React Server Components (RSC) весь код компонентов отправлялся в браузер - включая библиотеки, которые нужны только для рендеринга. **React Server Components** выполняются только на сервере: их код никогда не попадает в JS bundle клиента. Результат - меньший бандл, быстрее First Load JS, прямой доступ к БД без API.

В Next.js 13+ App Router все компоненты - серверные по умолчанию. Клиентский компонент помечается директивой `'use client'`. RSC может рендерить Client Components, но не наоборот - RSC не импортируется из Client компонентов.

**RSC vs SSR:** SSR выполняет компоненты на сервере, но всё равно отправляет их JS в браузер для hydration. RSC не отправляет JS вообще - только сериализованный результат рендера (RSC payload).

React Server Component делает прямой запрос к PostgreSQL. В браузер отправляется:

Hydration и island architecture

SSR возвращает HTML - страница видна немедленно. Но HTML статичен: кнопки не кликаются, формы не работают. **Hydration** - процесс «оживления»: браузер загружает JS, React «присоединяется» к уже существующему DOM, добавляет обработчики событий. До окончания hydration страница выглядит готовой, но не интерактивна.

**Island Architecture** решает проблему hydration целой страницы: вместо одного большого JS-бандла для всей страницы, интерактивность добавляется только к «островкам» - конкретным компонентам, которым нужен JS. Статичный контент остаётся чистым HTML. Astro реализует этот паттерн нативно.

**Partial hydration - будущее:** Progressive Enhancement + Island Architecture позволяют отправить минимум JS. E-commerce сайт на Astro - 90% страницы статичный HTML, 10% - интерактивные острова. Результат: TTI в 2-3 раза лучше, чем SPA.

После SSR страница отображается, но кнопки не реагируют на клики. Причина:

ISR: Incremental Static Regeneration

SSG генерирует HTML при сборке - максимальная скорость, но данные устаревают. SSR генерирует при каждом запросе - всегда свежие данные, но нагрузка на сервер. **ISR (Incremental Static Regeneration)** - компромисс: страницы статичны, но автоматически перегенерируются в фоне по расписанию или по запросу.

ISR работает по модели **stale-while-revalidate**: первый запрос после истечения TTL получает устаревшую страницу (быстро!), в фоне запускается регенерация. Следующий запрос - уже свежая страница. Пользователь никогда не ждёт регенерации.

**ISR vs Cache-Control:** ISR - это Next.js-специфичная абстракция над CDN-кешированием. На практике реализуется через `s-maxage` + `stale-while-revalidate` заголовки. Vercel, Netlify, Cloudflare Pages нативно поддерживают эту семантику.

ISR страница с revalidate=60. Запрос в 10:00:30 (страница сгенерирована в 10:00:00). Запрос в 10:01:30. Что получит второй пользователь?

Streaming SSR и Suspense

Классический SSR ждёт, пока все данные загрузятся, потом отправляет весь HTML. Если один запрос медленный - вся страница задержана. **Streaming SSR** отправляет HTML по частям: быстрый контент приходит немедленно, медленные части - когда готовы.

React Suspense - механизм объявить «эта часть ждёт данных». При Streaming SSR React отправляет сначала HTML с fallback (скелетон/спиннер), потом, когда данные готовы, стримит HTML-патч который заменяет fallback реальным контентом. Браузер начинает отображение немедленно.

**Streaming + TTFB:** Time to First Byte с Streaming SSR - миллисекунды (сразу отдаём shell страницы). Без streaming - TTFB равен времени самого медленного запроса. Google учитывает TTFB в Core Web Vitals.

SSR всегда медленнее CSR (client-side rendering) из-за нагрузки на сервер.

SSR с Streaming и RSC даёт лучший TTFB и FCP, чем CSR. Сервер ближе к данным, нет waterfall запросов из браузера.

CSR: браузер загружает JS (200-500ms), потом делает API запросы (100-300ms), потом рендерит. SSR: сервер рендерит на первом запросе, данные уже рядом. При хорошем кешировании разрыв огромный.

Страница имеет два Suspense boundary: быстрый (50мс) и медленный (2с). Когда пользователь увидит быстрый контент?

SSR и SSG: Next.js, Nuxt

  • RSC выполняются только на сервере: прямой доступ к БД, код не попадает в JS bundle клиента
  • Hydration - оживление SSR HTML через JS; Island Architecture добавляет JS только к интерактивным компонентам
  • ISR: статичные страницы + фоновая регенерация по TTL или on-demand webhook; stale-while-revalidate
  • Streaming SSR + Suspense: HTML стримится по частям, пользователь видит быстрый контент без ожидания медленных

Связанные темы

SSR и SSG - часть более широкой экосистемы производительности фронтенда:

  • Производительность фронтенда — Core Web Vitals измеряют эффект SSR/Streaming
  • HTTP и CDN — ISR реализуется через CDN cache-control заголовки
  • State Management — RSC меняет архитектуру: серверное состояние vs клиентское

Вопросы для размышления

  • Как определить, какой компонент должен быть Server Component, а какой Client Component?
  • В каких ситуациях ISR предпочтительнее чем SSR с кешированием на уровне CDN?
  • Как Streaming SSR меняет подход к дизайну компонентов - что нужно учитывать при разбивке на Suspense boundaries?

Связанные уроки

  • net-21-http-basics
SSR и SSG: Next.js, Nuxt

0

1

Войти