SSR vs CSR — производительность
SSR (Server-Side Rendering) генерирует HTML на сервере при каждом запросе; CSR (Client-Side Rendering) отдаёт пустой HTML и рендерит контент через JavaScript в браузере. Выбор влияет на FCP, LCP, TTI и SEO.
Зачем нужно
Правильный выбор стратегии рендеринга принципиален для производительности: CSR плохо работает на медленных устройствах и ухудшает LCP, SSR увеличивает нагрузку на сервер и TTFB. Современные фреймворки предлагают гибридные стратегии (SSG, ISR, RSC).
Где используется
- SSR: контент-сайты, e-commerce, SEO-критичные страницы, personalized content
- CSR: dashboard, admin-панели, приложения после логина
- SSG: блоги, документация, маркетинг (статический контент)
- ISR/RSC: Next.js, Astro — гибридный подход
Основной контент
Сравнение стратегий
CSR (Client-Side Rendering):
TTFB → Быстрый (статический shell)
FCP → Медленный (нужен JS для контента)
LCP → Медленный (данные после JS)
TTI → Медленный (hydration + data fetching)
SEO → Сложно (требует prerendering)
Сервер → Дешёвый (только статика)
SSR (Server-Side Rendering):
TTFB → Медленнее (генерация HTML)
FCP → Быстрый (HTML с контентом сразу)
LCP → Быстрый (контент в первом HTML)
TTI → После hydration (может быть долго)
SEO → Отличное (HTML с контентом)
Сервер → Дорогой (генерация на каждый запрос)
SSG (Static Site Generation):
TTFB → Минимальный (CDN)
FCP/LCP → Максимально быстрый
SEO → Отличное
Данные → Только статичные (без персонализации)
Waterfall проблема в CSR
CSR waterfall:
0ms → HTML получен (пустой)
100ms → JS бандл начал загрузку
800ms → JS выполнен, React инициализирован
900ms → API запрос за данными
1400ms → Данные получены, контент отрендерен
↑ LCP = 1400ms
SSR:
0ms → Запрос к серверу
200ms → HTML с контентом получен (TTFB)
↑ FCP/LCP = 200ms + render time
Next.js: выбор стратегии per page
// SSG — статическая генерация (по умолчанию в App Router)
// Генерируется один раз при сборке
export default async function BlogPost({ params }) {
const post = await getPost(params.slug);
return <Article post={post} />;
}
// SSR — динамический рендеринг при каждом запросе
export const dynamic = 'force-dynamic'; // Next.js 13+
// или
export const revalidate = 0;
// ISR — Incremental Static Regeneration (обновление каждые N секунд)
export const revalidate = 3600; // Обновлять каждый час
Гидрация и TTI
// Проблема: SSR контент виден, но не интерактивен до гидрации
// Пользователь видит кнопку и кликает — ничего не происходит
// Решение: прогрессивная гидрация (Islands Architecture)
// Гидрировать только интерактивные части, остальное — чистый HTML
// React 18: Selective Hydration
<Suspense fallback={<Skeleton />}>
<Comments /> {/* Гидрируется позже, не блокирует остальное */}
</Suspense>
Частые ошибки
- CSR для маркетинговых и SEO-критичных страниц — поисковики видят пустой HTML
- SSR для всего приложения — высокая нагрузка сервера, медленный TTFB при высоком трафике
- Гидрация без Suspense — блокирует TTI для всей страницы
- Смешение персонализированного и кешируемого контента в одном SSR запросе
Связанные темы
- _MOC Производительность
- Islands Architecture
- Метрики -- FCP, TTFB, TTI, TBT
- Edge Computing
- Кеширование -- Cache-Control