Веб-разработка
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?