SSR, SSG и ISR: как выбрать рендеринг под проект
Три способа отдавать страницы — сервер на каждый запрос, статика на билде или гибрид с фоновой регенерацией. Разбираем, что чем платит и когда какой брать.

Вы строите сайт на Next.js или Nuxt и упираетесь в вопрос: генерировать HTML на сервере при каждом запросе, собирать всё заранее в статику или что-то посередине. Выбор влияет на цену хостинга, время отклика и на то, как быстро посетитель увидит свежие данные. Ошибка тут стоит дорого: интернет-магазин с тысячами товаров на чистом SSR неожиданно кладёт сервер под нагрузкой, а блог на статике заставляет пересобирать весь сайт из-за одной опечатки.
Разберём три подхода — SSR, SSG и ISR — на примере Next.js (App Router, версия 14–15) и Nuxt 3, у каждого своя цена и своя область применения. Смежные темы вроде клиентского рендеринга (CSR) и стриминга компонентов не трогаем: здесь только выбор между рендерингом на запрос, на билде и гибридом.
Что означает каждый режим
SSR — рендеринг на каждый запрос
Сервер собирает HTML в момент, когда приходит запрос. Пользователь получает готовую страницу с актуальными данными. В Next.js App Router это поведение по умолчанию, если компонент читает динамические источники — cookies(), headers() или запрос с { cache: 'no-store' }. В Nuxt 3 это стандартный режим при ssr: true.
Плата — процессорное время на каждый визит. Страница, которую собирают 200 мс, при 300 одновременных запросах требует либо горизонтального масштабирования, либо очередь начнёт отдавать 502. Кеш перед сервером (CDN, reverse proxy) частично лечит проблему, но тогда вы теряете часть свежести — а ради неё SSR и брали.
SSG — генерация на билде
Все страницы собираются один раз при сборке проекта и лежат готовыми файлами. Сервер (или CDN) отдаёт их без вычислений — отсюда минимальная задержка и почти нулевая нагрузка. В Next.js страница становится статической, если не использует динамических источников; список путей для динамических маршрутов задаёт generateStaticParams. В Nuxt 3 за это отвечает пререндеринг через nitro.prerender.
Плата — данные замораживаются на момент билда. Изменили цену товара — она не обновится, пока не пройдёт новая сборка. Для 50 страниц это секунды, для 200 тысяч — десятки минут, и весь этот процесс запускается ради правки в одной карточке.
ISR — статика с фоновым обновлением
Incremental Static Regeneration — компромисс от Next.js. Страница отдаётся как статика, но помечается сроком жизни. По истечении срока первый пришедший запрос получает старую версию, а в фоне сервер пересобирает страницу, и следующие посетители видят свежую. Задаётся через export const revalidate = 60 (секунды) на уровне сегмента или через опцию next: { revalidate: 60 } в конкретном запросе.
Начиная с Next.js 12.2 доступна ещё и точечная регенерация по требованию — revalidatePath и revalidateTag, которые можно дёрнуть из вебхука CMS вместо ожидания таймера.
ISR не «SSR, но быстрее». Это статика, которая протухает по расписанию. Если вам нужно, чтобы каждый пользователь видел строго актуальную цену в свою секунду, ISR не подходит — между регенерациями все получают одно и то же закешированное значение.
Сравнение по цене вопроса
| Критерий | SSR | SSG | ISR |
|---|---|---|---|
| Когда собирается HTML | На каждый запрос | На билде | На билде + фоном по таймеру/вебхуку |
| Свежесть данных | Максимальная | На момент сборки | С задержкой до revalidate |
| Нагрузка на сервер | Высокая, растёт с трафиком | Почти нулевая | Низкая, всплески при регенерации |
| Время до первого байта | Зависит от рендера и БД | Минимальное (CDN) | Минимальное между регенерациями |
| Время билда | Не зависит от числа страниц | Растёт линейно | Можно собрать часть, остальное фоном |
| Персонализация под юзера | Да | Нет | Нет (одна версия на всех) |
Как режим включается в коде
В Next.js App Router режим не выбирают отдельной настройкой — он вытекает из того, какие данные читает компонент. Пример трёх серверных компонентов, каждый попадёт в свой режим.
// Next.js 14/15, App Router
// 1. SSG — данные без динамики, страница уйдёт в статику на билде
async function getPage(slug) {
const res = await fetch(`https://api.example.com/pages/${slug}`);
return res.json();
}
// 2. ISR — та же выборка, но с окном свежести 60 секунд
async function getProduct(id) {
const res = await fetch(`https://api.example.com/products/${id}`, {
next: { revalidate: 60 },
});
return res.json();
}
// 3. SSR — no-store заставляет рендерить на каждый запрос
async function getDashboard() {
const res = await fetch('https://api.example.com/dashboard', {
cache: 'no-store',
});
return res.json();
}Регенерация по вебхуку, когда контент правят в CMS, а не ждут таймера:
// app/api/revalidate/route.js — эндпоинт для вебхука
import { revalidatePath } from 'next/cache';
import { NextResponse } from 'next/server';
export async function POST(request) {
const secret = request.nextUrl.searchParams.get('secret');
// сравниваем с секретом из переменной окружения, а не хардкодом
if (secret !== process.env.REVALIDATE_SECRET) {
return NextResponse.json({ error: 'invalid token' }, { status: 401 });
}
const { slug } = await request.json();
revalidatePath(`/products/${slug}`); // пересоберётся только эта страница
return NextResponse.json({ revalidated: true });
}В Nuxt 3 режим на уровне маршрута задаётся в routeRules внутри nuxt.config.ts. Точные имена правил (prerender, swr, isr) и их поведение сверяйте с документацией Nitro вашей версии — набор опций там пополнялся между релизами.
Когда что выбирать
- Берите SSG, если контент меняется редко и его немного: лендинги, документация, блог с ручной публикацией. Пересборка на каждую правку терпима, зато хостинг почти бесплатный и падать нечему.
- Берите ISR, если страниц много и данные обновляются, но отставание в минуты не критично: карточки товаров, статьи новостного сайта, каталоги. Вебхук на
revalidatePathубирает даже это отставание для конкретных страниц. - Берите SSR, если контент завязан на конкретного пользователя или должен быть точным до секунды: личный кабинет, корзина с расчётом наличия, дашборд с живыми метриками. Здесь статику не закешировать — версии у всех разные.
Смешивать режимы в одном проекте — норма, а не компромисс. Каталог на ISR, карточка корзины на SSR, страница «О компании» на SSG. Next.js и Nuxt разрешают задавать режим на уровне маршрута.
Что ломается на практике
SSG: билд разрастается
При десятках тысяч динамических путей generateStaticParams собирает их все на билде, и время сборки уходит в десятки минут. Лечится тем, что часть путей отдаёте на догенерацию: возвращаете из generateStaticParams только популярные страницы, а остальные помечаете динамическими — Next.js соберёт их при первом обращении.
ISR: гонка при регенерации
Первый запрос после истечения revalidate получает устаревшую версию — это by design. Проблема, когда таких «первых» много одновременно: несколько инстансов могут начать регенерацию параллельно и дёрнуть вашу БД. На serverless-платформах поведение ISR-кеша между инстансами зависит от провайдера — на собственном хостинге кеш по умолчанию локальный для процесса, и в кластере это даёт рассинхрон. Проверяйте, где физически лежит ISR-кеш в вашем деплое.
SSR: медленный источник кладёт страницу
Если рендер ждёт ответа от внешнего API, а тот тормозит, растёт TTFB и копится очередь. Ставьте таймаут на внешние запросы и продумывайте фолбэк — иначе один тормозящий сервис останавливает весь рендеринг.
Что делать дальше
Определите для каждого типа страниц два числа: как часто данные реально меняются и сколько посетитель готов ждать устаревшую версию. Эти два числа и есть ваш выбор режима — не абстрактное «что лучше». Настройте на проекте измерение TTFB и доли попаданий в кеш (через логи CDN или заголовки ответа), после первого всплеска трафика вы увидите, какие маршруты стоит перевести с SSR на ISR. И сверьте актуальный синтаксис revalidate, revalidateTag и routeRules с документацией вашей версии фреймворка — API кеширования в Next.js менялся между 13, 14 и 15.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: Next.js Docs — Caching and Revalidating, Nuxt 3 — Rendering Modes
Частые вопросы
А если у меня Pages Router в Next.js, а не App Router?
ISR не пересобирает страницу, что проверить?
Можно ли ISR без Next.js, на чистом React или Vue?
SSR медленнее SSG всегда?
Что выбрать для интернет-магазина?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.