缓存和重新验证
缓存
¥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 theconst dynamic = 'force-dynamic'
orconst 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
要定期重新验证数据,你可以使用 fetch
的 next.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
可以使用 revalidatePath
和 revalidateTag
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.
-
使用
fetch
时,你可以选择使用一个或多个标签来标记缓存条目。¥When using
fetch
, you have the option to tag cache entries with one or more tags. -
然后,你可以调用
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
重新验证这个标记为 collection
的 fetch
调用:
¥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.