主题
cacheLife
cacheLife 函数用于设置函数或组件的缓存生存期。它应与 use cache 指令一起使用,并在函数或组件的范围内。
¥The cacheLife function is used to set the cache lifetime of a function or component. It should be used alongside the use cache directive, and within the scope of the function or component.
用法
¥Usage
基本设置
¥Basic setup
要使用 cacheLife,请先在 next.config.js 文件中启用 cacheComponents 标志:
¥To use cacheLife, first enable the cacheComponents flag in your next.config.js file:
ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
cacheComponents: true,
}
export default nextConfigcacheLife 需要 use cache 指令,该指令必须放置在文件级别或异步函数或组件的顶部。
¥cacheLife requires the use cache directive, which must be placed at the file level or at the top of an async function or component.
需要了解:
¥Good to know:
如果使用
cacheLife,即使use cache指令位于文件级别,也应将其放置在输出被缓存的函数内部。¥If used,
cacheLifeshould be placed within the function whose output is being cached, even when theuse cachedirective is at file level每次函数调用只能执行一次
cacheLife调用。你可以在不同的控制流分支中调用cacheLife,但要确保每次运行只执行一次。请参阅 条件缓存生命周期 示例¥Only one
cacheLifecall should execute per function invocation. You can callcacheLifein different control flow branches, but ensure only one executes per run. See the conditional cache lifetimes example
使用预设配置文件
¥Using preset profiles
Next.js 提供了预设的缓存配置文件,涵盖常见的缓存需求。每个配置文件都平衡了三个因素:
¥Next.js provides preset cache profiles that cover common caching needs. Each profile balances three factors:
用户无需检查更新即可查看缓存内容的时长(客户端)。
¥How long users see cached content without checking for updates (client-side)
服务器生成新内容的频率。
¥How often fresh content is generated on the server
旧内容完全过期时
¥When old content expires completely
根据内容更新频率选择配置文件:
¥Choose a profile based on how frequently your content changes:
seconds- 实时数据(股票价格、实时比分)¥
seconds- Real-time data (stock prices, live scores)minutes- 频繁更新(社交动态、新闻)¥
minutes- Frequently updated (social feeds, news)hours- 每日多次更新(产品库存、天气)¥
hours- Multiple daily updates (product inventory, weather)days- 每日更新(博客文章、文章)¥
days- Daily updates (blog posts, articles)weeks- 每周更新(播客、新闻简报)¥
weeks- Weekly updates (podcasts, newsletters)max- 很少更改(法律页面、存档内容)¥
max- Rarely changes (legal pages, archived content)
导入 cacheLife 并传递配置文件名称:
¥Import cacheLife and pass a profile name:
tsx
'use cache'
import { cacheLife } from 'next/cache'
export default async function BlogPage() {
cacheLife('days') // Blog content updated daily
const posts = await getBlogPosts()
return <div>{/* render posts */}</div>
}配置文件名称告诉 Next.js 如何缓存整个函数的输出。如果你不调用 cacheLife,则会使用 default 配置。请参阅 预设缓存配置文件 以了解计时详情。
¥The profile name tells Next.js how to cache the entire function's output. If you don't call cacheLife, the default profile is used. See preset cache profiles for timing details.
参考
¥Reference
缓存配置文件属性
¥Cache profile properties
缓存配置文件通过三个时间属性控制缓存行为:
¥Cache profiles control caching behavior through three timing properties:
stale:客户端无需检查服务器即可使用缓存数据的时长¥
stale: How long the client can use cached data without checking the serverrevalidate:经过此时间段后,下次请求将触发后台刷新。¥
revalidate: After this time, the next request will trigger a background refreshexpire:经过此时间段无请求后,下次请求将等待新内容。¥
expire: After this time with no requests, the next one waits for fresh content
stale
客户端:客户端无需检查服务器即可使用缓存数据的时长。
¥Client-side: How long the client can use cached data without checking the server.
在此期间,客户端路由会立即显示缓存的内容,而无需任何网络请求。经过此时间段后,路由必须在下次导航或请求时与服务器进行检查。此模式可从客户端缓存即时加载页面,但数据可能已过期。
¥During this time, the client-side router displays cached content immediately without any network request. After this period expires, the router must check with the server on the next navigation or request. This provides instant page loads from the client cache, but data may be outdated.
tsx
cacheLife({ stale: 300 }) // 5 minutesrevalidate
服务器在后台重新生成缓存内容的频率。
¥How often the server regenerates cached content in the background.
当请求在此时间段之后到达时,服务器:
¥When a request arrives after this period, the server:
立即提供缓存版本(如果可用)。
¥Serves the cached version immediately (if available)
在后台自动生成内容
¥Regenerates content in the background
使用最新内容更新缓存。
¥Updates the cache with fresh content
类似于 增量静态重生成 (ISR)
¥Similar to Incremental Static Regeneration (ISR)
tsx
cacheLife({ revalidate: 900 }) // 15 minutesexpire
服务器必须重新生成缓存内容的最长时间。
¥Maximum time before the server must regenerate cached content.
经过此时间段无流量后,服务器将在下次请求时同步重新生成内容。
¥After this period with no traffic, the server regenerates content synchronously on the next request
当你同时设置
revalidate和expire时,expire的长度必须大于revalidate。Next.js 会验证此设置,并对无效配置引发错误。¥When you set both
revalidateandexpire,expiremust be longer thanrevalidate. Next.js validates this and raises an error for invalid configurations.
tsx
cacheLife({ expire: 3600 }) // 1 hour预设缓存配置文件
¥Preset cache profiles
如果你不指定配置,Next.js 将使用 default 配置。我们建议显式设置配置文件,以便明确缓存行为。
¥If you don't specify a profile, Next.js uses the default profile. We recommend explicitly setting a profile to make caching behavior clear.
| 配置文件 | 用例 | stale | revalidate | expire |
|---|---|---|---|---|
default | 标准内容 | 5 分钟 | 15 分钟 | 1 年 |
seconds | 实时数据 | 30 秒 | 1 秒 | 1 分钟 |
minutes | 频繁更新的内容 | 5 分钟 | 1 分钟 | 1 小时 |
hours | 内容每天更新多次 | 5 分钟 | 1 小时 | 1 天 |
days | 内容每日更新 | 5 分钟 | 1 天 | 1 周 |
weeks | 内容每周更新 | 5 分钟 | 1 周 | 30 天 |
max | 稳定且很少更改的内容 | 5 分钟 | 30 天 | 1 年 |
自定义缓存配置文件
¥Custom cache profiles
在你的 next.config.ts 文件中定义可重用的缓存配置文件:
¥Define reusable cache profiles in your next.config.ts file:
ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
cacheComponents: true,
cacheLife: {
biweekly: {
stale: 60 * 60 * 24 * 14, // 14 days
revalidate: 60 * 60 * 24, // 1 day
expire: 60 * 60 * 24 * 14, // 14 days
},
},
}
export default nextConfig上述示例缓存 14 天,每天检查更新,并在 14 天后使缓存过期。然后,你可以通过其名称在整个应用中引用此配置文件:
¥The example above caches for 14 days, checks for updates daily, and expires the cache after 14 days. You can then reference this profile throughout your application by its name:
tsx
'use cache'
import { cacheLife } from 'next/cache'
export default async function Page() {
cacheLife('biweekly')
return <div>Page</div>
}覆盖默认值缓存配置文件
¥Overriding the default cache profiles
虽然默认缓存配置文件提供了一种有用的方法来思考可缓存输出的任何给定部分的新鲜度或陈旧度,但你可能更喜欢使用不同命名的配置文件来更好地与你的应用缓存策略保持一致。
¥While the default cache profiles provide a useful way to think about how fresh or stale any given part of cacheable output can be, you may prefer different named profiles to better align with your applications caching strategies.
你可以通过创建与默认配置同名的新配置来覆盖默认的命名缓存配置文件。
¥You can override the default named cache profiles by creating a new configuration with the same name as the defaults.
以下示例展示了如何覆盖默认的 "days" 缓存配置文件:
¥The example below shows how to override the default "days" cache profile:
ts
const nextConfig = {
cacheComponents: true,
cacheLife: {
// Override the 'days' profile
days: {
stale: 3600, // 1 hour
revalidate: 900, // 15 minutes
expire: 86400, // 1 day
},
},
}
export default nextConfig内联缓存配置文件
¥Inline cache profiles
对于一次性情况,请直接将配置文件对象传递给 cacheLife:
¥For one-off cases, pass a profile object directly to cacheLife:
tsx
'use cache'
import { cacheLife } from 'next/cache'
export default async function Page() {
cacheLife({
stale: 3600,
revalidate: 900,
expire: 86400,
})
return <div>Page</div>
}内联配置文件仅适用于特定函数或组件。对于可重用的配置,请在 next.config.ts 中定义自定义配置文件。
¥Inline profiles apply only to the specific function or component. For reusable configurations, define custom profiles in next.config.ts.
使用空对象并配置 cacheLife({}) 会应用 default 的配置文件值。
¥Using cacheLife({}) with an empty object applies the default profile values.
客户端路由缓存行为
¥Client router cache behavior
stale 属性控制客户端路由缓存,而不是 Cache-Control 标头:
¥The stale property controls the client-side router cache, not the Cache-Control header:
服务器通过
x-nextjs-stale-time响应头发送过期时间。¥The server sends the stale time via the
x-nextjs-stale-timeresponse header客户端路由使用此值来确定何时重新验证。
¥The client router uses this value to determine when to revalidate
为确保预取链接始终可用,强制执行至少 30 秒的等待时间。
¥Minimum of 30 seconds is enforced to ensure prefetched links remain usable
30 秒的最低等待时间可防止预取的数据在用户点击链接之前过期。它仅适用于基于时间的过期。
¥This 30-second minimum prevents prefetched data from expiring before users can click on links. It only applies to time-based expiration.
在服务器操作中调用重新验证函数(revalidateTag、revalidatePath、updateTag 或 refresh)时,整个客户端缓存会被立即清除,从而绕过缓存过期时间。
¥When you call revalidation functions from a Server Action (revalidateTag, revalidatePath, updateTag, or refresh), the entire client cache is immediately cleared, bypassing the stale time.
需要了解:
cacheLife中的stale属性与staleTimes中的不同。staleTimes是一个影响所有路由的全局设置,而cacheLife允许按函数或按路由进行配置。更新staleTimes.static也会更新default缓存配置文件的stale值。¥Good to know: The
staleproperty incacheLifediffers fromstaleTimes. WhilestaleTimesis a global setting affecting all routes,cacheLifeallows per-function or per-route configuration. UpdatingstaleTimes.staticalso updates thestalevalue of thedefaultcache profile.
示例
¥Examples
使用预设配置文件
¥Using preset profiles
配置缓存最简单的方法是使用预设配置文件。选择与你的内容更新模式相匹配的配置文件:
¥The simplest way to configure caching is using preset profiles. Choose one that matches your content's update pattern:
tsx
import { cacheLife } from 'next/cache'
export default async function BlogPost() {
'use cache'
cacheLife('days') // Blog posts updated daily
const post = await fetchBlogPost()
return <article>{post.content}</article>
}tsx
import { cacheLife } from 'next/cache'
export default async function ProductPage() {
'use cache'
cacheLife('hours') // Product data updated multiple times per day
const product = await fetchProduct()
return <div>{product.name}</div>
}针对特定需求的自定义配置文件
¥Custom profiles for specific needs
当预设选项不符合你的需求时,定义自定义配置文件:
¥Define custom profiles when preset options don't match your requirements:
ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
cacheComponents: true,
cacheLife: {
editorial: {
stale: 600, // 10 minutes
revalidate: 3600, // 1 hour
expire: 86400, // 1 day
},
marketing: {
stale: 300, // 5 minutes
revalidate: 1800, // 30 minutes
expire: 43200, // 12 hours
},
},
}
export default nextConfig然后在整个应用中使用这些配置文件:
¥Then use these profiles throughout your application:
tsx
import { cacheLife } from 'next/cache'
export default async function EditorialPage() {
'use cache'
cacheLife('editorial')
// ...
}针对特殊情况的内联配置文件
¥Inline profiles for unique cases
当特定函数需要一次性缓存行为时,请使用内联配置文件:
¥Use inline profiles when a specific function needs one-off caching behavior:
tsx
import { cacheLife } from 'next/cache'
import { getDb } from '@lib/db'
async function getLimitedOffer() {
'use cache'
cacheLife({
stale: 60, // 1 minute
revalidate: 300, // 5 minutes
expire: 3600, // 1 hour
})
const offer = await getDb().offer.findFirst({
where: { type: 'limited' },
orderBy: { created_at: 'desc' },
})
return offer
}
export async function GET() {
const offer = await getLimitedOffer()
return Response.json(offer)
}缓存单个函数
¥Caching individual functions
对实用函数应用缓存以实现更精细的控制:
¥Apply caching to utility functions for granular control:
tsx
import { cacheLife } from 'next/cache'
export async function getSettings() {
'use cache'
cacheLife('max') // Settings rarely change
return await fetchSettings()
}tsx
import { cacheLife } from 'next/cache'
export async function getRealtimeStats() {
'use cache'
cacheLife('seconds') // Stats update constantly
return await fetchStats()
}嵌套缓存行为
¥Nested caching behavior
嵌套 use cache 指令(一个缓存函数或组件使用另一个缓存函数或组件)时,外部缓存的行为取决于它是否显式指定了 cacheLife。
¥When you nest use cache directives (a cached function or component using another cached function or component), the outer cache's behavior depends on whether it has an explicit cacheLife.
使用显式外部缓存生命周期
¥With explicit outer cacheLife
外部缓存使用其自身的生命周期,不受内部缓存生命周期的影响。外部缓存命中时,它将返回包含所有嵌套数据的完整输出。显式指定的 cacheLife 始终优先,无论其生命周期长于还是短于内部生命周期。
¥The outer cache uses its own lifetime, regardless of inner cache lifetimes. When the outer cache hits, it returns the complete output including all nested data. An explicit cacheLife always takes precedence, whether it's longer or shorter than inner lifetimes.
tsx
import { cacheLife } from 'next/cache'
import { Widget } from './widget'
export default async function Dashboard() {
'use cache'
cacheLife('hours') // Outer scope sets its own lifetime
return (
<div>
<h1>Dashboard</h1>
<Widget /> {/* Inner scope has 'minutes' lifetime */}
</div>
)
}不使用显式外部缓存生命周期
¥Without explicit outer cacheLife
如果你不在外部缓存中调用 cacheLife,则会使用 default 配置(15 分钟重新验证)。生命周期较短的内部缓存会缩短外部缓存的 default 生命周期。生命周期较长的内部缓存无法延长其生命周期。
¥If you don't call cacheLife in the outer cache, it uses the default profile (15 min revalidate). Inner caches with shorter lifetimes can reduce the outer cache's default lifetime. Inner caches with longer lifetimes cannot extend it beyond the default.
tsx
import { Widget } from './widget'
export default async function Dashboard() {
'use cache'
// No cacheLife call - uses default (15 min)
// If Widget has 5 min → Dashboard becomes 5 min
// If Widget has 1 hour → Dashboard stays 15 min
return (
<div>
<h1>Dashboard</h1>
<Widget />
</div>
)
}建议显式指定 cacheLife。通过显式生命周期值,你可以检查缓存的函数或组件,并立即了解其行为,而无需追踪嵌套缓存。如果没有显式的生命周期值,行为将依赖于内部缓存的生命周期,这使得推断变得更加困难。
¥It is recommended to specify an explicit cacheLife. With explicit lifetime values, you can inspect a cached function or component and immediately know its behavior without tracing through nested caches. Without explicit lifetime values, the behavior becomes dependent on inner cache lifetimes, making it harder to reason about.
条件缓存生命周期
¥Conditional cache lifetimes
你可以在不同的代码路径中根据应用逻辑有条件地调用 cacheLife,以设置不同的缓存持续时间:
¥You can call cacheLife conditionally in different code paths to set different cache durations based on your application logic:
tsx
import { cacheLife, cacheTag } from 'next/cache'
async function getPostContent(slug: string) {
'use cache'
const post = await fetchPost(slug)
// Tag the cache entry for targeted revalidation
cacheTag(`post-${slug}`)
if (!post) {
// Content may not be published yet or could be in draft
// Cache briefly to reduce database load
cacheLife('minutes')
return null
}
// Published content can be cached longer
cacheLife('days')
// Return only the necessary data to keep cache size minimal
return post.data
}当不同的结果需要不同的缓存持续时间时,例如,当某个项目缺失但可能稍后可用时,此模式非常有用。
¥This pattern is useful when different outcomes need different cache durations, for example, when an item is missing but is likely to be available later.
根据数据使用动态缓存生命周期
¥Using dynamic cache lifetimes from data
如果你希望在运行时计算缓存生命周期(例如,通过从获取的数据中读取),请使用 内联缓存配置文件 对象:
¥If you want to calculate cache lifetime at runtime, for example by reading it from the fetched data, use an inline cache profile object:
tsx
import { cacheLife, cacheTag } from 'next/cache'
async function getPostContent(slug: string) {
'use cache'
const post = await fetchPost(slug)
cacheTag(`post-${slug}`)
if (!post) {
cacheLife('minutes')
return null
}
// Use cache timing from CMS data directly as an object
cacheLife({
// Ensure post.revalidateSeconds is a number in seconds
revalidate: post.revalidateSeconds ?? 3600,
})
return post.data
}