Инкрементальная статическая регенерация (ISR) в Next.js предлагает мощный способ сочетания статического и динамического контента. Благодаря возможности обновления статического контента без необходимости полной переработки сайта, ISR обеспечивает более масштабируемый и эффективный подход к управлению страницами. Это позволяет значительно снизить нагрузку на сервер, обрабатывать большие объемы контента и гарантировать, что пользователи видят актуальную информацию без ожидания полной регенерации всех страниц.
Мы можем обновлять статический контент, не создавая сайт заново. Это позволяет уменьшить нагрузку на сервер, предоставляя заранее отрендеренные статические страницы для большинства запросов. Мы можем обрабатывать большое количество контентных страниц, прежде чем время следующей генерации станет долгим.
Давайте начнем с примера:
export const revalidate = 30
export const dynamicParams = true
export async function generateStaticParams() {
const posts = await fetch('https://site.ru/posts/').then((res) =>
res.json()
)
return posts.map((post) => ({
id: String(post.id),
}))
}
export default async function Page({ params }) {
const post = await fetch(`https://site.ru/posts/${params.id}`).then(
(res) => res.json()
)
return (
<main>
<h1>{post.title}</h1>
<p>{post.content}</p>
</main>
)
}
Ну и как это работает?
Все запросы к этим страницам (например, /post/1) кэшируются и обрабатываются мгновенно. После 30 секунд следующий запрос все еще будет показывать кэшированную (устаревшую) страницу. Кэш становится недействительным, и новая версия страницы начинает генерироваться в фоновом режиме. Как только новая версия успешно сгенерирована, Next.js отобразит и кэширует обновленную страницу. Если будет запрошена страница /post/12, Next.js создаст и кэширует её по мере необходимости.
Если вам нужна более точная настройка, можно использовать валидацию по запросу, но если вам нужны данные в реальном времени, стоит рассмотреть возможность перехода на динамическую обработку.
Валидация по запросу с помощью revalidatePath
Next.js позволяет вручную очищать кэш конкретной страницы или маршрута. То есть, когда определённый контент обновляется, вместо того чтобы пересоздавать все страницы, вы можете обновить только изменённую страницу или контент.
Если вы хотите, чтобы страница обновлялась немедленно при внесении изменений (например, когда добавляется новый пост), вы можете запустить этот процесс, используя функцию revalidatePath. Другими словами, вы можете сделать так, чтобы новый контент появлялся сразу после его добавления.
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost() {
revalidatePath('/posts')
}
Валидация по запросу с помощью revalidateTag
В приложениях Next.js вы можете вручную очищать кэш, помечая определённые данные или контент. Это используется для очистки всего кэша данного контента, когда он обновляется. Когда контент изменяется, пользователи видят актуальные данные.
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog', {
next: { tags: ['posts'] },
})
const posts = await data.json()
// ...
}
После этого вы можете использовать функцию revalidateTag:
'use server'
import { revalidateTag } from 'next/cache'
export async function createPost() {
revalidateTag('posts')
}
ISR не поддерживается при создании статической экспорта. Если у вас есть несколько запросов на получение данных в статически рендеренной маршруте, и каждый из них имеет разную частоту регенерации, будет использоваться наименьшее время для ISR. Однако эти частоты регенерации всё равно будут учитываться в кэше данных.
Если любой из запросов на получение данных в маршруте имеет время регенерации 0 или явный параметр no-store, маршрут будет динамически рендериться. Промежуточное ПО не будет выполняться для запросов пользователей по запросу, что означает, что любые изменения путей или логика в промежуточном ПО не будут применены. Убедитесь, что вы выполняете регенерацию для точного пути. Например, используйте /post/1, а не изменённый /post-1.
Заключение
ISR является оптимальным решением для проектов, в которых контент обновляется часто, но полная динамическая рендеризация не требуется. Однако в сценариях, где важны данные в реальном времени, более подходящим может быть переход на динамическую обработку.