Skip to main content

增量静态再生 (ISR)

Examples

Next.js 允许你在构建网站后创建或更新静态页面。增量静态重新生成 (ISR) 使你能够在每个页面上使用静态生成,而无需重建整个站点。借助 ISR,你可以在扩展到数百万页的同时保留静态的优势。

¥Next.js allows you to create or update static pages after you’ve built your site. Incremental Static Regeneration (ISR) enables you to use static-generation on a per-page basis, without needing to rebuild the entire site. With ISR, you can retain the benefits of static while scaling to millions of pages.

很高兴知道:尽管你可以通过手动设置 cache-control 标头来利用 stale-while-revalidate,但 edge 运行时间 目前与 ISR 不兼容。

¥Good to know: The edge runtime is currently not compatible with ISR, although you can leverage stale-while-revalidate by setting the cache-control header manually.

要使用 ISR,请将 revalidate 属性添加到 getStaticProps

¥To use ISR, add the revalidate prop to getStaticProps:

function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}

// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()

return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 10 seconds
revalidate: 10, // In seconds
}
}

// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// the path has not been generated.
export async function getStaticPaths() {
const res = await fetch('https://.../posts')
const posts = await res.json()

// Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))

// We'll pre-render only these paths at build time.
// { fallback: 'blocking' } will server-render pages
// on-demand if the path doesn't exist.
return { paths, fallback: 'blocking' }
}

export default Blog

当对构建时预渲染的页面发出请求时,它将首先显示缓存的页面。

¥When a request is made to a page that was pre-rendered at build time, it will initially show the cached page.

  • 在初始请求之后和 10 秒之前对页面的任何请求也会被缓存并且是即时的。

    ¥Any requests to the page after the initial request and before 10 seconds are also cached and instantaneous.

  • 10 秒窗口后,下一个请求仍将显示缓存的(过时)页面

    ¥After the 10-second window, the next request will still show the cached (stale) page

  • Next.js 在后台触发页面的重新生成。

    ¥Next.js triggers a regeneration of the page in the background.

  • 页面生成成功后,Next.js 将使缓存失效并显示更新后的页面。如果后台重新生成失败,旧页面仍将保持不变。

    ¥Once the page generates successfully, Next.js will invalidate the cache and show the updated page. If the background regeneration fails, the old page would still be unaltered.

当向尚未生成的路径发出请求时,Next.js 将在第一个请求上服务器渲染页面。未来的请求将从缓存中提供静态文件。Vercel 全局保存缓存并处理回滚 上的 ISR。

¥When a request is made to a path that hasn’t been generated, Next.js will server-render the page on the first request. Future requests will serve the static file from the cache. ISR on Vercel persists the cache globally and handles rollbacks.

很高兴知道:检查你的上游数据提供程序是否默认启用缓存。你可能需要禁用(例如 useCdn: false),否则重新验证将无法提取新数据来更新 ISR 缓存。当 CDN 返回 Cache-Control 标头时,缓存可能会发生在 CDN(对于正在请求的端点)。

¥Good to know: Check if your upstream data provider has caching enabled by default. You might need to disable (e.g. useCdn: false), otherwise a revalidation won't be able to pull fresh data to update the ISR cache. Caching can occur at a CDN (for an endpoint being requested) when it returns the Cache-Control header.

按需重新验证

¥On-Demand Revalidation

如果你将 revalidate 时间设置为 60,则所有访问者将在一分钟内看到你网站的相同生成版本。使缓存失效的唯一方法是有人在一分钟过去后访问该页面。

¥If you set a revalidate time of 60, all visitors will see the same generated version of your site for one minute. The only way to invalidate the cache is from someone visiting that page after the minute has passed.

v12.2.0 开始,Next.js 支持按需增量静态重新生成,以手动清除特定页面的 Next.js 缓存。这使得你可以在以下情况下更轻松地更新你的网站:

¥Starting with v12.2.0, Next.js supports On-Demand Incremental Static Regeneration to manually purge the Next.js cache for a specific page. This makes it easier to update your site when:

  • 创建或更新无头 CMS 中的内容

    ¥Content from your headless CMS is created or updated

  • 电子商务元数据更改(价格、描述、类别、评论等)

    ¥Ecommerce metadata changes (price, description, category, reviews, etc.)

getStaticProps 内,你无需指定 revalidate 即可使用按需重新验证。如果省略 revalidate,Next.js 将使用默认值 false(不重新验证),并且仅在调用 revalidate() 时按需重新验证页面。

¥Inside getStaticProps, you do not need to specify revalidate to use on-demand revalidation. If revalidate is omitted, Next.js will use the default value of false (no revalidation) and only revalidate the page on-demand when revalidate() is called.

很高兴知道:中间件 不会针对按需 ISR 请求执行。相反,请在你想要重新验证的确切路径上调用 revalidate()。例如,如果你有 pages/blog/[slug].js 并从 /post-1 -> /blog/post-1 重写,则需要调用 res.revalidate('/blog/post-1')

¥Good to know: Middleware won't be executed for On-Demand ISR requests. Instead, call revalidate() on the exact path that you want revalidated. For example, if you have pages/blog/[slug].js and a rewrite from /post-1 -> /blog/post-1, you would need to call res.revalidate('/blog/post-1').

使用按需重新验证

¥Using On-Demand Revalidation

首先,创建一个只有你的 Next.js 应用知道的秘密令牌。此秘密将用于防止未经授权访问重新验证 API 路由。你可以使用以下 URL 结构访问路由(手动或使用 Webhook):

¥First, create a secret token only known by your Next.js app. This secret will be used to prevent unauthorized access to the revalidation API Route. You can access the route (either manually or with a webhook) with the following URL structure:

https://<your-site.com>/api/revalidate?secret=<token>

接下来,将密钥作为 环境变量 添加到你的应用中。最后,创建重新验证 API 路由:

¥Next, add the secret as an Environment Variable to your application. Finally, create the revalidation API Route:

export default async function handler(req, res) {
// Check for secret to confirm this is a valid request
if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
return res.status(401).json({ message: 'Invalid token' })
}

try {
// this should be the actual path not a rewritten path
// e.g. for "/blog/[slug]" this should be "/blog/post-1"
await res.revalidate('/path-to-revalidate')
return res.json({ revalidated: true })
} catch (err) {
// If there was an error, Next.js will continue
// to show the last successfully generated page
return res.status(500).send('Error revalidating')
}
}

查看我们的演示 查看正在执行的按需重新验证并提供反馈。

¥View our demo to see on-demand revalidation in action and provide feedback.

在开发过程中测试按需 ISR

¥Testing on-Demand ISR during development

当使用 next dev 在本地运行时,每个请求都会调用 getStaticProps。要验证你的按需 ISR 配置是否正确,你需要创建 生产构建 并启动 生产服务器

¥When running locally with next dev, getStaticProps is invoked on every request. To verify your on-demand ISR configuration is correct, you will need to create a production build and start the production server:

$ next build
$ next start

然后,你可以确认静态页面已成功重新验证。

¥Then, you can confirm that static pages have successfully revalidated.

错误处理和重新验证

¥Error handling and revalidation

如果处理后台生成时 getStaticProps 内部出现错误,或者你手动抛出错误,则将继续显示上次成功生成的页面。在下一个后续请求中,Next.js 将重试调用 getStaticProps

¥If there is an error inside getStaticProps when handling background regeneration, or you manually throw an error, the last successfully generated page will continue to show. On the next subsequent request, Next.js will retry calling getStaticProps.

export async function getStaticProps() {
// If this request throws an uncaught error, Next.js will
// not invalidate the currently shown page and
// retry getStaticProps on the next request.
const res = await fetch('https://.../posts')
const posts = await res.json()

if (!res.ok) {
// If there is a server error, you might want to
// throw an error instead of returning so that the cache is not updated
// until the next successful request.
throw new Error(`Failed to fetch posts, received status ${res.status}`)
}

// If the request was successful, return the posts
// and revalidate every 10 seconds.
return {
props: {
posts,
},
revalidate: 10,
}
}

自托管 ISR

¥Self-hosting ISR

当你使用 next start 时,增量静态再生 (ISR) 可在 自托管 Next.js 站点 上开箱即用。

¥Incremental Static Regeneration (ISR) works on self-hosted Next.js sites out of the box when you use next start.

了解有关 自托管 Next.js 的更多信息。

¥Learn more about self-hosting Next.js.

版本历史

¥Version History

版本变化
v14.1.0定制 cacheHandler 稳定。
v12.2.0按需 ISR 稳定
v12.1.0添加了按需 ISR(测试版)。
v12.0.0添加了 机器人感知 ISR 后备
v9.5.0添加了基本路径。