cacheLife 函数用于设置函数或组件的缓存生命周期。它应与 use cache 指令配合使用,并位于函数或组件的作用域内。
要使用 cacheLife,首先在您的 next.config.js 文件中启用 cacheComponents 标志:
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
cacheComponents: true,
}
export default nextConfigconst nextConfig = {
cacheComponents: true,
}
export default nextConfigcacheLife 需要 use cache 指令,该指令必须放置在文件级别或异步函数或组件的顶部。
须知:
- 如果使用,
cacheLife应该放置在正在缓存其输出的函数内部,即使use cache指令位于文件级别- 每个函数调用只应执行一次
cacheLife。您可以在不同的控制流分支中调用cacheLife,但要确保每次运行只执行一次。请参阅条件缓存生命周期示例
Next.js 提供了预设的缓存配置文件,涵盖了常见的缓存需求。每个配置文件平衡了三个因素:
根据您的内容更改频率选择一个配置文件:
seconds - 实时数据(股票价格、实时比分)minutes - 频繁更新(社交动态、新闻)hours - 每日多次更新(产品库存、天气)days - 每日更新(博客文章、文章)weeks - 每周更新(播客、时事通讯)max - 很少更改(法律页面、存档内容)导入 cacheLife 并传入配置文件名称:
'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 配置文件。有关计时详细信息,请参阅预设缓存配置文件。
缓存配置文件通过三个计时属性控制缓存行为:
stale: 客户端在不检查服务器的情况下可以使用缓存数据的时间revalidate: 此时间过后,下一个请求将触发后台刷新expire: 此时间过后若无请求,下一个请求将等待新内容stale客户端: 客户端在不检查服务器的情况下可以使用缓存数据的时间。
在此期间,客户端路由会立即显示缓存内容,无需任何网络请求。此期限过后,路由必须在下一次导航或请求时与服务器进行检查。这提供了从客户端缓存即时加载页面的能力,但数据可能已过时。
cacheLife({ stale: 300 }) // 5 minutesrevalidate服务器在后台重新生成缓存内容的频率。
cacheLife({ revalidate: 900 }) // 15 minutesexpire服务器必须重新生成缓存内容的最长时间。
revalidate 和 expire 时,expire 必须长于 revalidate。Next.js 会对此进行验证,并对无效配置引发错误。cacheLife({ expire: 3600 }) // 1 hour如果您未指定配置文件,Next.js 会使用 default 配置文件。我们建议明确设置配置文件,以使缓存行为清晰明了。
| Profile | Use Case | stale | revalidate | expire |
|---|---|---|---|---|
default | 标准内容 | 5 minutes | 15 minutes | 1 year |
seconds | 实时数据 | 30 seconds | 1 second | 1 minute |
minutes | 频繁更新的内容 | 5 minutes | 1 minute | 1 hour |
hours | 每日多次更新的内容 | 5 minutes | 1 hour | 1 day |
days | 每日更新的内容 | 5 minutes | 1 day | 1 week |
weeks | 每周更新的内容 | 5 minutes | 1 week | 30 days |
max | 很少更改的稳定内容 | 5 minutes | 30 days | 1 year |
在您的 next.config.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 nextConfigconst 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
},
},
}
module.exports = nextConfig上述示例缓存 14 天,每天检查更新,并在 14 天后使缓存过期。然后,您可以在整个应用程序中通过其名称引用此配置文件:
'use cache'
import { cacheLife } from 'next/cache'
export default async function Page() {
cacheLife('biweekly')
return <div>Page</div>
}尽管默认缓存配置文件提供了一种有用的方式来思考可缓存输出的任何给定部分的新鲜度或陈旧度,但您可能更喜欢不同的命名配置文件,以便更好地与您的应用程序缓存策略对齐。
您可以通过创建与默认配置文件同名的新配置来覆盖默认命名缓存配置文件。
以下示例展示了如何覆盖默认的 "days" 缓存配置文件:
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对于一次性情况,直接将配置文件对象传递给 cacheLife:
'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 中定义自定义配置文件。
使用空对象 cacheLife({}) 将应用 default 配置文件值。
stale 属性控制客户端路由缓存,而不是 Cache-Control 标头:
x-nextjs-stale-time 响应头发送失效时间这个 30 秒的最小值可以防止预取数据在用户点击链接之前过期。它仅适用于基于时间的过期。
当您从 Server Action 调用重新验证函数时 (revalidateTag、revalidatePath、updateTag 或 refresh),整个客户端缓存会立即清除,绕过失效时间。
须知:
cacheLife中的stale属性与staleTimes不同。staleTimes是影响所有路由的全局设置,而cacheLife允许按函数或按路由配置。更新staleTimes.static也会更新default缓存配置文件的stale值。
配置缓存最简单的方法是使用预设配置文件。选择一个与您内容更新模式相匹配的:
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>
}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>
}当预设选项不符合您的要求时,定义自定义配置文件:
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然后,在整个应用程序中使用这些配置文件:
import { cacheLife } from 'next/cache'
export default async function EditorialPage() {
'use cache'
cacheLife('editorial')
// ...
}当特定函数需要一次性缓存行为时,使用内联配置文件:
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)
}将缓存应用于工具函数以进行精细控制:
import { cacheLife } from 'next/cache'
export async function getSettings() {
'use cache'
cacheLife('max') // Settings rarely change
return await fetchSettings()
}import { cacheLife } from 'next/cache'
export async function getRealtimeStats() {
'use cache'
cacheLife('seconds') // Stats update constantly
return await fetchStats()
}当您嵌套 use cache 指令时 (一个缓存函数或组件使用了另一个缓存函数或组件),外部缓存的行为取决于它是否具有显式的 cacheLife。
cacheLife外部缓存使用其自身的生命周期,无论内部缓存生命周期如何。当外部缓存命中时,它会返回完整的输出,包括所有嵌套数据。显式的 cacheLife 总是优先,无论它比内部生命周期长还是短。
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>
)
}cacheLife如果您不在外部缓存中调用 cacheLife,它会使用 default 配置文件(15 分钟重新验证)。具有较短生命周期的内部缓存可以缩短外部缓存的 default 生命周期。具有较长生命周期的内部缓存不能将其延长超出默认值。
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。 拥有显式生命周期值,您可以检查缓存函数或组件并立即了解其行为,而无需追溯嵌套缓存。如果没有显式生命周期值,其行为将依赖于内部缓存生命周期,使其更难理解。
您可以在不同的代码路径中条件性地调用 cacheLife,以根据您的应用逻辑设置不同的缓存持续时间:
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
}当不同的结果需要不同的缓存持续时间时,此模式非常有用,例如,当某个项目缺失但稍后可能会可用时。
如果您想在运行时计算缓存生命周期,例如通过从获取的数据中读取,请使用内联缓存配置文件对象:
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
}