Cache Components
2026年9月6日
Cache Components 是 Next 16 的可选能力:同一页里,构建期能确定的先做成静态壳,请求期才知道的放进 Suspense 洞里流式补上,需要的动态数据还可以显式缓存。用来缓和「全静态不能更新」和「全动态首屏慢」两边的别扭。
先在配置里打开:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
cacheComponents: true,
};
export default nextConfig;
ts
三种内容
| 类型 | 何时算 | 例子 |
|---|---|---|
| 静态 | 构建 / 预渲染 | fs.readFileSync、静态 import、纯计算 |
| 动态 | 每次请求 | fetch 实时接口、cookies()、headers() |
| 缓存动态 | 算一次,按策略复用 | 'use cache' + cacheLife |
动态块必须包在 Suspense 里,外壳才能先出去。
静态块
import { readFileSync } from "node:fs";
export default function Page() {
const json = JSON.parse(readFileSync("data.json", "utf8"));
return <h1>{json.title}</h1>;
}
tsx
没有网络、没有用户上下文,构建时就能定稿。
动态块
import { Suspense } from "react";
import { cookies } from "next/headers";
async function Who() {
const res = await fetch("https://api.example.com/name");
const data = await res.json();
const jar = await cookies();
return (
<p>
{data.name} / cookie: {jar.get("token")?.value ?? "无"}
</p>
);
}
export default function Page() {
return (
<div>
<h1>首页</h1>
<Suspense fallback={<p>加载动态区…</p>}>
<Who />
</Suspense>
</div>
);
}
tsx
底层接近 PPR:先出带占位的静态 HTML,动态结果随后替换对应槽。开发者工具里能看到占位 id 和替换脚本,不必手写。
随机数、时间戳
Math.random()、Date.now() 每次都不同。开启 Cache Components 后,如果在预渲染阶段同步调用,框架会报错,避免「随机值被冻住」。
先 await connection(),明确告诉框架:这段等真正有请求再跑。
import { connection } from "next/server";
import { Suspense } from "react";
async function Live() {
await connection();
return <p>{Math.random()}</p>;
}
export default function Page() {
return (
<Suspense fallback={<p>…</p>}>
<Live />
</Suspense>
);
}
tsx
use cache 和 cacheLife
把动态结果缓存起来,并声明寿命:
import { cacheLife } from "next/cache";
import { Suspense } from "react";
async function CachedName() {
"use cache";
cacheLife("hours");
const res = await fetch("https://api.example.com/name");
return <p>{(await res.json()).name}</p>;
}
export default function Page() {
return (
<Suspense fallback={<p>…</p>}>
<CachedName />
</Suspense>
);
}
tsx
cacheLife 可以传预设名,或自己写秒数:
| 预设 | 大致用途 |
|---|---|
seconds | 行情、比分 |
minutes | 时间线 |
hours | 天气、库存 |
days | 博客正文 |
weeks | 更新很慢的栏目 |
max | 几乎不变的页 |
三个字段:stale(客户端先信多久)、revalidate(过后后台再生成)、expire(多久没人访问就彻底丢掉)。
下一篇把「没开 Cache Components」时的 revalidate / force-dynamic / cache: 'no-store' 也放在一起。