Skip to main content

缓存和重新验证

缓存

¥Caching

缓存是存储数据以减少对服务器发出的请求数量的过程。Next.js 为单个数据请求提供内置 数据缓存,让你可以精细控制缓存行为。

¥Caching is the process of storing data to reduce the number of requests made to the server. Next.js provides a built-in Data Cache for individual data requests, giving you granular control of caching behavior.

fetch 请求

¥fetch requests

默认情况下,fetch 请求在运行时获取新数据。

¥By default, fetch requests fetch fresh data at runtime.

要缓存单个 fetch 请求,你可以使用 cache: 'force-cache' 选项:

¥To cache an individual fetch request, you can use the cache: 'force-cache' option:

// 'force-cache' is the default, and can be omitted
fetch('https://...', { cache: 'force-cache' })

要选择退出单个 fetch 请求的缓存,你可以使用 cache: 'no-store' 选项:

¥To opt out of caching for individual fetch requests, you can use the cache: 'no-store' option:

fetch('https://...', { cache: 'no-store' })

高级:如果你在布局或页面段中有多个 fetch 请求,则可以使用 const dynamic = 'force-dynamic'const fetchCache = 'force-no-store' 片段配置选项 配置段中所有数据请求的缓存行为。

¥Advanced: If you have multiple fetch requests in a layout or page segment, you can configure the caching behavior of all data requests in the segment using the const dynamic = 'force-dynamic' or const fetchCache = 'force-no-store' Segment Config Options.

数据获取库和 ORM

¥Data fetching libraries and ORMs

数据请求是否被缓存将取决于数据获取库、数据库客户端或 ORM 的默认语义。

¥Whether a data request is cached will depend on the default semantics of your Data Fetching Library, Database Client, or ORM.

要缓存特定请求,你可以使用 unstable_cache API:

¥To cache specific requests, you can use the unstable_cache API:

import { unstable_cache as cache } from 'next/cache'

export async function getPosts() {
cache()

try {
// Fetch Data
} catch (error) {}
}
import { unstable_cache as cache } from 'next/cache'

export async function getPosts() {
cache()
try {
// Fetch Data
} catch (error) {}
}

要选择退出缓存的特定请求,你可以使用 unstable_noStore API:

¥To opt specific requests out of caching, you can use the unstable_noStore API:

import { unstable_noStore as noStore } from 'next/cache'

export async function getTransactions() {
// Prevent the response from being cached.
// This is equivalent to in fetch(..., {cache: 'no-store'}).
noStore()

try {
// Fetch Data
} catch (error) {}
}
import { unstable_noStore as noStore } from 'next/cache'

export async function getTransactions() {
// Prevent the response from being cached.
// This is equivalent to in fetch(..., {cache: 'no-store'}).
noStore()

try {
// Fetch Data
} catch (error) {}
}

重新验证数据

¥Revalidating data

重新验证是清除数据缓存并重新获取最新数据的过程。当你的数据发生变化并且你想确保显示最新信息同时仍能从静态渲染速度中受益时,这很有用。

¥Revalidation is the process of purging the Data Cache and re-fetching the latest data. This is useful when your data changes and you want to ensure you show the latest information while still benefiting from the speed of static rendering.

可以通过两种方式重新验证缓存的数据:

¥Cached data can be revalidated in two ways:

  • 基于时间的重新验证:经过一定时间后自动重新验证数据。这对于不经常更改且新鲜度不那么重要的数据非常有用。

    ¥Time-based revalidation: Automatically revalidate data after a certain amount of time has passed. This is useful for data that changes infrequently and freshness is not as critical.

  • 按需重新验证:根据事件(例如表单提交)手动重新验证数据。按需重新验证可以使用基于标签或基于路径的方法立即重新验证数据组。当你想要确保尽快显示最新数据时(例如,当更新无头 CMS 的内容时),这非常有用。

    ¥On-demand revalidation: Manually revalidate data based on an event (e.g. form submission). On-demand revalidation can use a tag-based or path-based approach to revalidate groups of data at once. This is useful when you want to ensure the latest data is shown as soon as possible (e.g. when content from your headless CMS is updated).

基于时间的重新验证

¥Time-based revalidation

要定期重新验证数据,你可以使用 fetchnext.revalidate 选项来设置资源的缓存生命周期(以秒为单位)。

¥To revalidate data at a timed interval, you can use the next.revalidate option of fetch to set the cache lifetime of a resource (in seconds).

fetch('https://...', { next: { revalidate: 3600 } }) // revalidate at most every hour

或者,要重新验证路由段中的所有请求,你可以使用 片段配置选项

¥Alternatively, to revalidate all requests in a route segment, you can use the Segment Config Options.

export const revalidate = 3600 // revalidate at most every hour

学习 基于时间的重新验证的工作原理

¥Learn how time-based revalidation works

很高兴知道:

¥Good to know:

  • 如果静态渲染的路由中有多个提取请求,并且每个请求都有不同的重新验证频率。所有请求都将使用最短的时间。

    ¥If you have multiple fetch requests in a statically rendered route, and each has a different revalidation frequency. The lowest time will be used for all requests.

  • 对于动态渲染的路由,每个 fetch 请求都将独立重新验证。

    ¥For dynamically rendered routes, each fetch request will be revalidated independently.

  • 为了节省服务器资源,我们建议尽可能设置较长的重新验证时间。例如,1 小时而不是 1 秒。如果你需要实时数据,请考虑切换到 动态渲染 或客户端数据获取。

    ¥To save server resources, we recommend setting a high revalidation time whenever possible. For instance, 1 hour instead of 1 second. If you need real-time data, consider switching to dynamic rendering or client-side data fetching.

按需重新验证

¥On-demand revalidation

可以使用 revalidatePathrevalidateTag API 按需重新验证数据。

¥Data can be revalidated on-demand with the revalidatePath and revalidateTag APIs.

服务器操作路由处理程序 中使用 revalidatePath 重新验证特定路由的数据:

¥Use revalidatePath in Server Actions or Route Handler to revalidate data for specific routes:

import { revalidatePath } from 'next/cache'

export default async createPost() {
try {
// Mutate data
revalidatePath('/posts')
} catch(error) {}

}
import { revalidatePath } from 'next/cache'

export default async createPost() {
try {
// Mutate data
revalidatePath('/posts')
} catch(error) {}

}

使用 revalidateTag 重新验证跨路由的 fetch 请求。

¥Use revalidateTag to revalidate fetch requests across routes.

  1. 使用 fetch 时,你可以选择使用一个或多个标签来标记缓存条目。

    ¥When using fetch, you have the option to tag cache entries with one or more tags.

  2. 然后,你可以调用 revalidateTag 来重新验证与该标签关联的所有条目。

    ¥Then, you can call revalidateTag to revalidate all entries associated with that tag.

例如,以下 fetch 请求添加缓存标签 collection

¥For example, the following fetch request adds the cache tag collection:

export default async function Page() {
const res = await fetch('https://...', { next: { tags: ['collection'] } })
const data = await res.json()
// ...
}
export default async function Page() {
const res = await fetch('https://...', { next: { tags: ['collection'] } })
const data = await res.json()
// ...
}

然后,你可以通过调用 revalidateTag 重新验证这个标记为 collectionfetch 调用:

¥You can then revalidate this fetch call tagged with collection by calling revalidateTag:

'use server'

import { revalidateTag } from 'next/cache'

export default async function action() {
revalidateTag('collection')
}
'use server'

import { revalidateTag } from 'next/cache'

export default async function action() {
revalidateTag('collection')
}

学习 按需重新验证的工作原理

¥Learn how on-demand revalidation works.

错误处理和重新验证

¥Error handling and revalidation

如果在尝试重新验证数据时抛出错误,则将继续从缓存中提供最后成功生成的数据。在下一个后续请求中,Next.js 将重试重新验证数据。

¥If an error is thrown while attempting to revalidate data, the last successfully generated data will continue to be served from the cache. On the next subsequent request, Next.js will retry revalidating the data.