Skip to main content

use cache

use cache 指令允许你将某个路由、React 组件或函数标记为可缓存。你可以在文件顶部添加该指令,表示该文件中所有导出的内容都将被缓存;也可以在组件或函数顶部内联使用,实现对返回值的缓存。

用法​

use cache 目前属于实验性特性。要启用它,请在 next.config.ts 文件中添加 useCache 选项:

next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
experimental: {
useCache: true,
},
}

export default nextConfig

提示: 你也可以通过 dynamicIO 选项启用 use cache。

然后,在文件、组件或函数级别添加 use cache:

// 文件级别
'use cache'

export default async function Page() {
// ...
}

// 组件级别
export async function MyComponent() {
'use cache'
return <></>
}

// 函数级别
export async function getData() {
'use cache'
const data = await fetch('/api/data')
return data
}

use cache 的工作原理​

缓存键​

缓存条目的 key 是通过对其输入进行序列化生成的,主要包括:

  • 构建 ID(每次构建都会生成)
  • 函数 ID(每个函数唯一的安全标识符)
  • 可序列化 的函数参数(或 props)

传递给被缓存函数的参数,以及它从父作用域读取的任何值,都会自动成为缓存 key 的一部分。也就是说,只要输入相同,就会复用同一个缓存条目。

非可序列化参数​

任何不可序列化的参数、props 或闭包中的值,在缓存函数内部会变成引用,只能传递,无法被检查或修改。这些不可序列化的值会在请求时被填充,不会成为缓存 key 的一部分。

例如,一个被缓存的函数可以接收 JSX 作为 children prop 并返回 <div>{children}</div>,但无法检查 children 对象的实际内容。这允许你在缓存组件内部嵌套未缓存的内容。

app/ui/cached-component.tsx
function CachedComponent({ children }: { children: ReactNode }) {
'use cache'
return <div>{children}</div>
}

返回值​

可缓存函数的返回值必须是可序列化的。这样才能确保缓存数据能够被正确存储和读取。

构建时的 use cache​

当你在 layout 或 page 文件顶部使用 use cache 时,该路由段会被预渲染,从而支持后续的再验证。

这意味着 use cache 不能与 请求时 API(如 cookies 或 headers)一起使用。

运行时的 use cache​

在服务端,各个组件或函数的缓存条目会存储在内存中。

在客户端,从服务端缓存返回的内容会存储在浏览器内存中,持续到会话结束或被再验证。

再验证期间​

默认情况下,use cache 的服务端再验证周期为 15 分钟。如果你的内容不需要频繁更新,这个周期可能已经足够。你也可以通过 cacheLife 和 cacheTag API 配置每个缓存条目的再验证时机。

  • cacheLife:配置缓存条目的生命周期。
  • cacheTag:为按需再验证创建标签。

这两个 API 会在客户端和服务端缓存层之间协同工作,你可以在一个地方配置缓存策略,并在全局生效。

更多信息请参阅 cacheLife 和 cacheTag 的 API 文档。

示例​

使用 use cache 缓存整个路由​

要预渲染整个路由,需要在 layout 和 page 文件顶部都添加 use cache。每个路由段都会作为应用的独立入口被单独缓存。

app/layout.tsx
'use cache'

export default function Layout({ children }: { children: ReactNode }) {
return <div>{children}</div>
}
app/page.tsx
'use cache'

export default function Layout({ children }) {
return <div>{children}</div>
}

在 page 文件中导入和嵌套的所有组件都会继承 page 的缓存行为。

app/page.tsx
'use cache'

async function Users() {
const users = await fetch('/api/users')
// 遍历用户列表
}

export default function Page() {
return (
<main>
<Users />
</main>
)
}

提示:

  • 如果只在 layout 或 page 文件中添加 use cache,则只有该路由段及其导入的组件会被缓存。
  • 如果路由中的任何嵌套子组件使用了 动态 API,该路由将不会被预渲染。

使用 use cache 缓存组件输出​

你可以在组件级别使用 use cache,缓存该组件内部的 fetch 或计算操作。只要序列化后的 props 保持一致,缓存条目就会被复用。

app/components/bookings.tsx
export async function Bookings({ type = 'haircut' }: BookingsProps) {
'use cache'
async function getBookingsData() {
const data = await fetch(`/api/bookings?type=${encodeURIComponent(type)}`)
return data
}
return //...
}

interface BookingsProps {
type: string
}

使用 use cache 缓存函数输出​

你可以在任何异步函数中添加 use cache,不仅限于组件或路由。比如缓存网络请求、数据库查询或耗时计算。

app/actions.ts
export async function getData() {
'use cache'

const data = await fetch('/api/data')
return data
}

交错(Interleaving)​

如果你需要向可缓存函数传递不可序列化的参数,可以通过 children 传递。这样,children 的引用变化不会影响缓存条目。

app/page.tsx
export default async function Page() {
const uncachedData = await getData()
return (
<CacheComponent>
<DynamicComponent data={uncachedData} />
</CacheComponent>
)
}

async function CacheComponent({ children }: { children: ReactNode }) {
'use cache'
const cachedData = await fetch('/api/cached-data')
return (
<div>
<PrerenderedComponent data={cachedData} />
{children}
</div>
)
}

你还可以通过缓存组件将 Server Actions 传递给客户端组件,而无需在可缓存函数内部调用它们。

app/page.tsx
import ClientComponent from './ClientComponent'

export default async function Page() {
const performUpdate = async () => {
'use server'
// 执行服务端更新
await db.update(...)
}

return <CacheComponent performUpdate={performUpdate} />
}

async function CachedComponent({
performUpdate,
}: {
performUpdate: () => Promise<void>
}) {
'use cache'
// 不要在这里调用 performUpdate
return <ClientComponent action={performUpdate} />
}
app/ClientComponent.tsx
'use client'

export default function ClientComponent({
action,
}: {
action: () => Promise<void>
}) {
return <button onClick={action}>Update</button>
}

平台支持​

部署选项是否支持
Node.js 服务器支持
Docker 容器支持
静态导出不支持
适配器取决于平台

了解如何在自托管 Next.js 时配置缓存。

版本历史​

版本变更内容
v15.0.0"use cache" 作为实验性特性引入。