Инкрементальная статическая регенерация (ISR)
Next.js позволяет создавать или обновлять статические страницы после сборки вашего сайта. Инкрементальная статическая регенерация (ISR) позволяет использовать статическую генерацию для отдельных страниц, без необходимости пересобирать весь сайт. С ISR вы сохраняете преимущества статики, масштабируясь до миллионов страниц.
Полезно знать: В настоящее время
edge
runtime несовместим с ISR, хотя вы можете использоватьstale-while-revalidate
, вручную устанавливая заголовокcache-control
.
Чтобы использовать ISR, добавьте свойство revalidate
в getStaticProps
:
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
// Эта функция вызывается во время сборки на стороне сервера.
// Она может быть вызвана снова в serverless-функции, если
// включена ревалидация и поступает новый запрос
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.js попытается регенерировать страницу:
// - При поступлении запроса
// - Не чаще чем раз в 10 секунд
revalidate: 10, // В секундах
}
}
// Эта функция вызывается во время сборки на стороне сервера.
// Она может быть вызвана снова в serverless-функции, если
// путь не был сгенерирован.
export async function getStaticPaths() {
const res = await fetch('https://.../posts')
const posts = await res.json()
// Получаем пути для предварительного рендеринга на основе постов
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// Предварительно рендерим только эти пути во время сборки.
// { fallback: 'blocking' } будет рендерить страницы
// по запросу, если путь не существует.
return { paths, fallback: 'blocking' }
}
export default Blog
При запросе страницы, которая была предварительно отрендерена во время сборки, изначально будет показана закешированная версия.
- Все последующие запросы к странице в течение 10 секунд также будут мгновенно возвращать закешированный результат.
- По истечении 10-секундного интервала следующий запрос всё равно покажет устаревшую (stale) закешированную страницу.
- Next.js запустит фоновую регенерацию страницы.
- После успешной генерации страницы Next.js инвалидирует кеш и покажет обновлённую версию. Если фоновая регенерация завершится ошибкой, старая страница останется без изменений.
При запросе пути, который не был сгенерирован, Next.js выполнит серверный рендеринг страницы при первом запросе. Последующие запросы будут обслуживать статический файл из кеша. На Vercel ISR сохраняет кеш глобально и поддерживает откаты.
Полезно знать: Проверьте, включено ли кеширование у вашего провайдера данных. Возможно, его потребуется отключить (например,
useCdn: false
), иначе ревалидация не сможет получить свежие данные для обновления ISR-кеша. Кеширование может происходить на CDN (для запрашиваемого эндпоинта), если он возвращает заголовокCache-Control
.
Ревалидация по требованию
Если вы установите revalidate
в 60
, все посетители будут видеть одну и ту же сгенерированную версию вашего сайта в течение минуты. Единственный способ инвалидировать кеш — это когда кто-то посетит страницу после истечения минуты.
Начиная с версии v12.2.0
, Next.js поддерживает инкрементальную статическую регенерацию по требованию для ручной очистки кеша Next.js для конкретной страницы. Это упрощает обновление сайта в случаях, когда:
- Создаётся или обновляется контент из вашей headless CMS
- Изменяются метаданные электронной коммерции (цена, описание, категория, отзывы и т. д.)
Внутри getStaticProps
вам не нужно указывать revalidate
для использования ревалидации по требованию. Если revalidate
не указан, Next.js будет использовать значение по умолчанию false
(без ревалидации) и ревалидировать страницу только по требованию при вызове revalidate()
.
Полезно знать: Middleware не будет выполняться для запросов ISR по требованию. Вместо этого вызывайте
revalidate()
для точного пути, который нужно ревалидировать. Например, если у вас естьpages/blog/[slug].js
и реврайт с/post-1
->/blog/post-1
, вам нужно вызватьres.revalidate('/blog/post-1')
.
Использование ревалидации по требованию
Сначала создайте секретный токен, известный только вашему приложению Next.js. Этот секрет будет использоваться для предотвращения несанкционированного доступа к API-маршруту ревалидации. Вы можете обратиться к маршруту (вручную или через вебхук) по следующему URL:
https://<ваш-сайт.com>/api/revalidate?secret=<токен>
Затем добавьте секрет как переменную окружения в ваше приложение. Наконец, создайте API-маршрут для ревалидации:
export default async function handler(req, res) {
// Проверяем секрет для подтверждения валидности запроса
if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
return res.status(401).json({ message: 'Неверный токен' })
}
try {
// Это должен быть фактический путь, а не реврайт
// Например, для "/blog/[slug]" это должен быть "/blog/post-1"
await res.revalidate('/path-to-revalidate')
return res.json({ revalidated: true })
} catch (err) {
// При ошибке Next.js продолжит показывать
// последнюю успешно сгенерированную страницу
return res.status(500).send('Ошибка ревалидации')
}
}
Посмотрите наше демо для примера ревалидации по требованию и оставьте отзыв.
Тестирование ISR по требованию во время разработки
При локальном запуске с next dev
функция getStaticProps
вызывается при каждом запросе. Чтобы проверить правильность конфигурации ISR по требованию, вам нужно создать продакшен-сборку и запустить продакшен-сервер:
$ next build
$ next start
Затем вы можете убедиться, что статические страницы успешно ревалидируются.
Обработка ошибок и ревалидация
Если в getStaticProps
при фоновой регенерации возникает ошибка или вы вручную выбрасываете ошибку, будет продолжена отображение последней успешно сгенерированной страницы. При следующем запросе Next.js повторно вызовет getStaticProps
.
export async function getStaticProps() {
// Если этот запрос выбросит необработанную ошибку, Next.js
// не инвалидирует текущую страницу и
// повторит вызов getStaticProps при следующем запросе.
const res = await fetch('https://.../posts')
const posts = await res.json()
if (!res.ok) {
// При ошибке сервера можно выбросить ошибку,
// чтобы кеш не обновлялся до следующего успешного запроса.
throw new Error(`Не удалось загрузить посты, статус ${res.status}`)
}
// При успешном запросе возвращаем посты
// и ревалидируем каждые 10 секунд.
return {
props: {
posts,
},
revalidate: 10,
}
}
Самостоятельный хостинг ISR
Инкрементальная статическая регенерация (ISR) работает на самостоятельно размещённых Next.js сайтах из коробки при использовании next start
.
Вы можете использовать этот подход при развёртывании в оркестраторах контейнеров, таких как Kubernetes или HashiCorp Nomad. По умолчанию сгенерированные ассеты хранятся в памяти каждого пода. Это означает, что каждый под будет иметь свою копию статических файлов. Устаревшие данные могут отображаться до тех пор, пока запрос не попадёт на конкретный под.
Для обеспечения согласованности между всеми подами вы можете отключить кеширование в памяти. Это заставит сервер Next.js использовать только ассеты, сгенерированные ISR в файловой системе.
Вы можете использовать общую сетевую точку монтирования в ваших подах Kubernetes (или аналогичную настройку) для повторного использования одного и того же кеша файловой системы между разными контейнерами. При совместном использовании одной точки монтирования папка .next
, содержащая кеш next/image
, также будет общей.
Чтобы отключить кеширование в памяти, установите isrMemoryCacheSize
в 0
в файле next.config.js
:
module.exports = {
experimental: {
// По умолчанию 50MB
isrMemoryCacheSize: 0, // размер кеша в байтах
},
}
Полезно знать: Возможно, вам придётся учитывать состояние гонки между несколькими подами, пытающимися обновить кеш одновременно, в зависимости от конфигурации вашей общей точки монтирования.
История версий
Версия | Изменения |
---|---|
v12.2.0 | ISR по требованию стабилизирована |
v12.1.0 | Добавлена ISR по требованию (бета). |
v12.0.0 | Добавлен fallback для ISR с учётом ботов. |
v9.5.0 | Добавлен Base Path. |
Статическая генерация сайтов (SSG)
Используйте статическую генерацию сайтов (SSG) для предварительного рендеринга страниц во время сборки.
Автоматическая статическая оптимизация
Next.js автоматически оптимизирует ваше приложение для генерации статического HTML, когда это возможно. Узнайте, как это работает.