Как обновлять страницы при использовании SSG, если данные меняются
Что проверяют
Понимаете ли вы, что статическая страница сама не узнает об изменении данных, и какие есть способы её обновить с разной ценой. Следом обычно спрашивают, что увидит пользователь сразу после изменения и как обновить страницу мгновенно, не дожидаясь таймера.
Как отвечать
Способы от грубого к точному:
- полная пересборка: CMS по вебхуку запускает сборку и деплой. Годится и для чистой статики, но на тысячах страниц сборка долгая, а смена одной цены пересобирает всё;
- ISR по времени: в Next.js App Router это
export const revalidate = 60в сегменте илиfetch(url, { next: { revalidate: 60 } }), в Pages Router полеrevalidateизgetStaticProps. Схема stale-while-revalidate: первый запрос после истечения срока получает старую версию и запускает фоновую перегенерацию, свежую увидит следующий; - ISR по событию:
revalidatePathилиrevalidateTagиз роута, который дёргает вебхук CMS, обновляется только изменённое. В Next.js 16 уrevalidateTagпоявился второй аргумент с профилем кеша, а для Server Actions естьupdateTag, после которого автор изменения сразу видит свежие данные; - новые страницы без пересборки:
generateStaticParamsотдаёт часть путей, остальные генерируются при первом запросе и кешируются; - клиентская догрузка: статичный каркас, а быстро меняющиеся части вроде остатка запрашиваются в браузере через SWR или TanStack Query.
Выбор объясняйте через требования к свежести: блог спокойно живёт с обновлением раз в час, карточке товара с ценой нужно обновление по событию.
Где спотыкаются
Думают, что revalidate: 60 сам обновляет страницу каждую минуту. Без запросов ничего не пересобирается, а первый посетитель после срока всё равно видит старую версию.
Включают ISR при output: "export". У статического экспорта нет сервера, поэтому ни перегенерации по времени, ни revalidatePath там нет, остаётся только пересборка.
Случайно делают страницу динамической: чтение cookies(), headers() или searchParams, даже в общем layout, отключает статическую генерацию, и revalidate теряет смысл. А с включённым cacheComponents сегментного revalidate нет, там работают "use cache" и cacheLife.