В Next.js доступны три стратегии рендеринга: статика (SSG), серверный рендер по запросу (SSR) и инкрементальная регенерация (ISR). Их часто путают, и выбор не очевиден. Разберём по полочкам.
SSG: статическая генерация
При сборке (next build) генерируются HTML-файлы для всех страниц. Деплой — это копирование готовой статики на CDN. Запрос пользователя — мгновенный ответ из кеша.
Плюсы: максимальная скорость, минимум серверных ресурсов, отличный SEO. Минусы: данные «застывают» на момент билда. Если у вас 10 000 страниц товаров, каждая обновляющаяся пять раз в день — статика бесполезна без перебилда.
Когда использовать: статьи блога, страницы услуг, лендинги, документация. Всё, что меняется редко (раз в день или реже).
SSR: серверный рендер на каждый запрос
Каждый запрос — это рендер на сервере. HTML генерируется заново, данные актуальны на момент клика. В Next.js App Router это поведение по умолчанию для динамических роутов или при использовании cookies(), headers(), searchParams.
Плюсы: всегда свежие данные, поддержка персонализации (показ контента в зависимости от юзера). Минусы: нагрузка на сервер растёт линейно с трафиком, время ответа выше (200-800 мс против 20-50 мс у статики).
Когда использовать: личный кабинет, дашборды, страницы с приватными данными, корзина, оформление заказа.
ISR: лучшее из двух миров
ISR — это статика с отложенной перегенерацией. Страница рендерится статически, но через указанный интервал (revalidate: 3600) или по сигналу (revalidatePath) пересобирается фоном. Пользователи видят кеш, пока новая версия не готова.
Плюсы: скорость статики плюс умеренная актуальность данных. Подходит для большинства публичных страниц с регулярными обновлениями. Минусы: первая после revalidate-периода загрузка может быть медленной (если страница не была сгенерирована заранее), требует поддержки на хостинге.
Когда использовать: каталог товаров, страницы с актуализированной ценой, новости, главная страница с динамическими блоками.
Гибридные подходы
В одном проекте обычно живут все три стратегии. Пример e-commerce:
- Главная — ISR с revalidate 5 минут
- Каталог категории — ISR с revalidate 1 минута
- Карточка товара — ISR с revalidate 10 минут плюс webhook-инвалидация при изменении цены
- Корзина и оформление — SSR (динамика, привязка к юзеру)
- Личный кабинет — SSR
- Блог — SSG (полная статика)
- О компании — SSG
Это даёт оптимальный баланс скорости и свежести данных.
On-demand revalidation
Вместо ожидания таймера можно сбрасывать кеш по событию. Webhook от админки при публикации новой статьи вызывает revalidatePath("/blog/[slug]") — конкретная страница пересобирается при следующем запросе.
В Next.js 15 это работает через теги: вы помечаете fetch-ы тегом, потом сбрасываете все связанные через revalidateTag("products"). Это удобно, когда одна сущность отображается на десятках страниц.
Streaming и Partial Prerendering
Partial Prerendering (PPR) — экспериментальная фича, которая позволяет совмещать статику и динамику в одной странице. Шапка и шаблон — статические, конкретные блоки внутри — динамические через Suspense. Это потенциально лучшее решение для страниц с малой долей персонализации.
Streaming с loading.tsx тоже снимает часть проблем SSR: пользователь видит каркас страницы немедленно, контентные блоки подгружаются по мере готовности.
Стоимость инфраструктуры
SSG — самый дешёвый: статика отдаётся CDN, серверу делать почти нечего. SSR — самый дорогой: каждый запрос — это работа CPU и базы данных. ISR — средняя нагрузка плюс нужен Redis или встроенное хранилище кеша.
На Vercel это решается автоматически. На своём сервере (Yandex Cloud, Selectel) ISR требует постоянного хранилища между перезапусками — иначе после рестарта весь кеш заново.
Итого
Выбор стратегии — это про компромисс между свежестью данных, скоростью и стоимостью. SSG — для статики, SSR — для динамики и приватности, ISR — для всего среднего. Большинство страниц публичного сайта подходят под ISR с разными интервалами.
Частые вопросы
Чем отличаются SSG, SSR и ISR в Next.js?
SSG — при сборке (next build) генерируются HTML-файлы для всех страниц, деплой это копирование статики на CDN. SSR — каждый запрос это рендер на сервере, HTML генерируется заново, данные актуальны. ISR — статика с отложенной перегенерацией: страница рендерится статически, но через указанный интервал (revalidate) или по сигналу (revalidatePath) пересобирается фоном. SSG — самый быстрый и дешёвый, SSR — всегда свежий но дорогой, ISR — компромисс.
Когда использовать SSG для страниц сайта?
Когда данные меняются редко (раз в день или реже). Подходит для статей блога, страниц услуг, лендингов, документации. Плюсы: максимальная скорость, минимум серверных ресурсов, отличный SEO. Минусы: данные «застывают» на момент билда. Если у вас 10 000 страниц товаров, каждая обновляющаяся пять раз в день — статика бесполезна без перебилда. Также SSG требует, чтобы при добавлении контента запускался полный билд, что не всегда практично.
Когда нужен SSR на каждый запрос?
Когда нужны всегда свежие данные и поддержка персонализации. Личный кабинет, дашборды, страницы с приватными данными, корзина, оформление заказа. В Next.js App Router это поведение по умолчанию для динамических роутов или при использовании cookies(), headers(), searchParams. Минусы: нагрузка на сервер растёт линейно с трафиком, время ответа выше (200-800 мс против 20-50 мс у статики). Не используйте SSR для публичных страниц, которые могли бы быть статикой.
Что такое ISR и когда он лучше всего работает?
ISR — это статика с отложенной перегенерацией. Страница рендерится статически, но через указанный интервал (revalidate: 3600) или по сигналу (revalidatePath) пересобирается фоном. Пользователи видят кеш, пока новая версия не готова. Подходит для каталога товаров, страниц с актуализированной ценой, новостей, главной с динамическими блоками. Большинство страниц публичного сайта подходят под ISR с разными интервалами — от 1 минуты для каталога до часа для лендингов.
Как смешивать SSG, SSR и ISR в одном проекте?
В одном проекте обычно живут все три стратегии. Пример e-commerce. Главная — ISR с revalidate 5 минут. Каталог категории — ISR с revalidate 1 минута. Карточка товара — ISR с revalidate 10 минут плюс webhook-инвалидация при изменении цены. Корзина и оформление — SSR (динамика, привязка к юзеру). Личный кабинет — SSR. Блог — SSG (полная статика). О компании — SSG. Это даёт оптимальный баланс скорости и свежести данных.
Как сбрасывать кеш ISR по событию вместо ожидания таймера?
Вместо ожидания таймера можно сбрасывать кеш по событию. Webhook от админки при публикации новой статьи вызывает revalidatePath("/blog/[slug]") — конкретная страница пересобирается при следующем запросе. В Next.js 15 это работает через теги: вы помечаете fetch-ы тегом, потом сбрасываете все связанные через revalidateTag("products"). Это удобно, когда одна сущность отображается на десятках страниц. On-demand revalidation даёт мгновенную инвалидацию без ожидания TTL.