缓存策略
2026年9月6日
Next 默认能缓存的都缓存:路由预渲染、fetch 结果复用。开发时每次刷新都像「最新」,next build && next start 之后可能发现随机图片冻住了——因为这条路由被当成静态页了。
先分清你有没有开 cacheComponents。
未开启时
配置里关掉或不写:
const nextConfig = {
cacheComponents: false,
};
ts
构建日志里常见:
○静态预渲染ƒ动态,每次请求现算
下面这个页面开发看着会变,生产构建后可能一直同一张图:
export default async function Page() {
const res = await fetch("https://example.com/random.json");
const data = await res.json();
return <img src={data.url} alt="" />;
}
tsx
退出缓存有几条路,选一条就够。
1. 整页 revalidate
export const revalidate = 5; // 秒;0 表示不缓存
tsx
过期后下一次请求触发重新生成。
2. 强制动态
export const dynamic = "force-dynamic";
tsx
这条路由不当静态页。开了 Cache Components 之后,默认已经偏动态,一般不用再写。
3. 单次 fetch 不存
await fetch(url, { cache: "no-store" });
tsx
4. 碰动态 API
用了下面任意一个,路由会按动态处理:
cookies()headers()connection()- 读请求上的
searchParams fetch(..., { cache: "no-store" })
import { connection } from "next/server";
export default async function Page() {
await connection();
const res = await fetch("https://example.com/random.json");
// ...
}
tsx
开启 Cache Components 之后
cacheComponents: true 时,组件默认按动态内容处理,动态部分用 Suspense 包起来。构建日志里可能多一个:
◐部分预渲染:外壳静态,洞里的内容请求时再流式补
import { Suspense } from "react";
async function RandomImage() {
const res = await fetch("https://example.com/random.json");
const data = await res.json();
return <img src={data.url} alt="" />;
}
export default function Page() {
return (
<div>
<h1>首页</h1>
<Suspense fallback={<p>Loading…</p>}>
<RandomImage />
</Suspense>
</div>
);
}
tsx
要缓存动态结果,回到上一篇的 'use cache' + cacheLife,不要混用旧的 export const dynamic 当主开关。
怎么选
| 目标 | 未开 Cache Components | 已开 |
|---|---|---|
| 尽量静态 | 什么都别标 | 别读 cookie / 别乱 fetch |
| 隔一会儿更新 | revalidate = n | use cache + cacheLife |
| 每次都新 | force-dynamic 或 no-store | Suspense + 动态 API |
下一篇开始内置组件:next/image。