增量静态再生 (ISR)
增量静态再生 (ISR) 使你能够:
- 无需重新构建整个网站就能更新静态内容
- 通过对大多数请求提供预渲染的静态页面来减少服务器负载
- 确保页面自动添加正确的
cache-control
headers - 在不增加
next build
时间的情况下处理大量内容页面
下面是一个最小示例:
这个示例的工作原理如下:
- 在
next build
期间,生成所有已知的博客文章 (本示例中有 25 篇) - 对这些页面的所有请求 (例如
/blog/1
) 都被缓存并立即响应 - 60 秒过后,下一个请求仍然会显示缓存的 (陈旧的) 页面
- 缓存失效,并在后台开始生成页面的新版本
- 一旦成功生成,Next.js 将显示并缓存更新后的页面
- 如果请求
/blog/26
,Next.js 将按需生成并缓存这个页面
参考
路由段配置
函数
示例
基于时间的重新验证
这段代码在 /blog
路径下获取并显示博客文章列表。一小时后,在下次访问页面时该页面的缓存将失效。然后在后台,将使用最新的博客文章生成页面的新版本。
我们建议设置较长的重新验证时间。例如,设置为 1 小时而不是 1 秒。如果你需要更精确的控制,可以考虑使用按需重新验证。如果你需要实时数据,可以考虑切换到动态渲染。
使用 revalidatePath
进行按需重新验证
对于更精确的重新验证方法,可以使用 revalidatePath
函数进行按需重新验证。
例如,这个服务器操作会在添加新文章后被调用。无论你在服务器组件中如何获取数据,无论是使用 fetch
还是连接数据库,这都将清除整个路由的缓存,并允许服务器组件获取新的数据。
使用 revalidateTag
进行按需重新验证
对于大多数用例,建议重新验证整个路径。如果你需要更细粒度的控制,可以使用 revalidateTag
函数。例如,你可以为单个 fetch
调用添加标签:
如果你正在使用 ORM 或连接数据库,可以使用 unstable_cache
:
然后你可以在服务器操作或路由处理程序中使用 revalidateTag
:
处理未捕获的异常
如果在尝试重新验证数据时抛出错误,将继续从缓存中提供最后一次成功生成的数据。在下一次后续请求中,Next.js 将重试重新验证数据。了解更多关于错误处理的信息。
自定义缓存位置
缓存和重新验证页面(使用增量静态再生)使用相同的共享缓存。当部署到 Vercel 时,ISR 缓存会自动持久化到持久存储中。
在自托管时,ISR 缓存存储在 Next.js 服务器的文件系统(磁盘)中。这在使用页面路由器和应用路由器进行自托管时都会自动工作。
如果你想将缓存的页面和数据持久化到持久存储中,或者在 Next.js 应用程序的多个容器或实例之间共享缓存,可以配置 Next.js 缓存位置。了解更多。
故障排除
在本地开发中调试缓存数据
如果你使用 fetch
API,可以添加额外的日志来了解哪些请求被缓存或未缓存。了解更多关于 logging
选项。
验证正确的生产行为
要验证你的页面在生产环境中是否正确缓存和重新验证,你可以通过运行 next build
然后 next start
来在本地运行生产版 Next.js 服务器进行测试。
这将允许你测试 ISR 行为,就像在生产环境中一样。要进行进一步的调试,在你的 .env
文件中添加以下环境变量:
这将使 Next.js 服务器在控制台记录 ISR 缓存命中和未命中。你可以检查输出,查看在 next build
期间生成了哪些页面,以及在按需访问路径时页面是如何更新的。
注意事项
- ISR 仅在使用 Node.js 运行时(默认)时受支持。
- ISR 在创建静态导出时不受支持。
- 如果在静态渲染的路由中有多个
fetch
请求,每个请求的revalidate
频率不同,则将使用最低的时间进行 ISR。然而,这些重新验证频率仍将被数据缓存所遵守。 - 如果在路由中使用的任何
fetch
请求的revalidate
时间为0
,或者显式设置了no-store
,该路由将被动态渲染。 - 中间件不会在按需 ISR 请求时执行,这意味着中间件中的任何路径重写或逻辑都不会被应用。确保你重新验证的是准确的路径。例如,使用
/post/1
而不是重写后的/post-1
。
版本历史
版本 | 变更 |
---|---|
v14.1.0 | 自定义 cacheHandler 功能稳定。 |
v13.0.0 | 引入 App Router。 |
v12.2.0 | Pages Router: 按需 ISR 功能稳定。 |
v12.0.0 | Pages Router: 添加机器人感知 ISR 回退。 |
v9.5.0 | Pages Router: 引入稳定版 ISR。 |