Что такое ISR (Incremental Static Regeneration) в Next.js и почему это гибрид
Что проверяют
Понимаете ли вы, откуда берётся HTML в разных режимах Next.js и когда страница обновляется на самом деле. Следом обычно спрашивают, что будет, если данные поменялись прямо сейчас, и почему страница с revalidate вдруг стала динамической.
Как отвечать
ISR это статическая страница, которую сервер умеет пересобрать уже после деплоя, не трогая остальной сайт. Механика stale-while-revalidate:
- рендер: при сборке или при первом запросе, результат кладётся в кэш;
- свежая копия: пока не истёк
revalidate, все получают готовый HTML; - устаревание: первый запрос после истечения тоже получает старую версию, но запускает фоновую перегенерацию;
- обновление: следующие запросы видят свежую страницу, а если перегенерация упала, остаётся прежняя.
Гибрид потому, что от SSG взята отдача готового HTML из кэша, а от SSR работающий сервер, который рендерит страницу в рантайме. Поэтому ISR недоступен при output: 'export': там сервера нет.
В App Router время задаётся export const revalidate = 60 в сегменте или fetch(url, { next: { revalidate: 60 } }). Для динамических маршрутов generateStaticParams перечисляет, что собрать заранее, остальное соберётся при первом заходе. Обновление по событию: revalidatePath или revalidateTag, в Next 16 с профилем вторым аргументом, например revalidateTag('posts', 'max'), а updateTag в Server Actions нужен, когда пользователь должен сразу увидеть свою правку. В Pages Router то же делают revalidate из getStaticProps и res.revalidate().
Где спотыкаются
Думают, что revalidate: 60 обновляет страницу по таймеру раз в минуту. Без запросов ничего не пересобирается, а первый посетитель после паузы видит старые данные.
Вызывают cookies(), headers() или читают searchParams где-то в дереве страницы, включая layout. Маршрут становится динамическим, и revalidate молча перестаёт действовать.
Разворачивают несколько экземпляров next start и удивляются разным версиям страницы: кэш по умолчанию у каждого инстанса свой, нужен общий cacheHandler, например на Redis. Ещё одна ловушка: проверять ISR в next dev, где страница рендерится на каждый запрос.