
Next.js App Router 默认对 fetch 请求启用强缓存(force-cache),导致 SSG 生成的页面始终返回构建时的旧数据;需通过 cache: 'no-store' 或 next: { revalidate: N } 显式控制缓存策略。
next.js app router 默认对 `fetch` 请求启用强缓存(`force-cache`),导致 ssg 生成的页面始终返回构建时的旧数据;需通过 `cache: 'no-store'` 或 `next: { revalidate: n }` 显式控制缓存策略。
在 Next.js App Router 中,fetch 不再是“裸调用”,而是深度集成于数据缓存与渲染生命周期中。当你在 generateStaticParams 或服务端组件中调用 fetch 时,默认行为是 cache: 'force-cache' —— 即请求仅在构建阶段执行一次,结果被持久化缓存,后续所有请求(包括部署后的新访问)均直接返回该缓存副本,完全忽略 API 端的真实变更。这正是你看到 content 始终为旧值的根本原因。
要解决此问题,必须显式覆盖默认缓存策略。以下是三种推荐方案,按适用场景排序:
✅ 方案一:禁用缓存(适用于实时性要求高的动态内容)
在 fetchPosts 和 generateStaticParams 的 fetch 调用中添加 cache: 'no-store':
const fetchPosts = async (params) => {
const res = await fetch(
`https://5875183d-18c0-49ad-b99d-8deeb4ded6a9.mock.pstmn.io/posts/${params.slug}`,
{ cache: 'no-store' } // ← 关键:每次请求都重新发起
);
return res.json();
};
export const generateStaticParams = async () => {
const res = await fetch(
"https://5875183d-18c0-49ad-b99d-8deeb4ded6a9.mock.pstmn.io/posts",
{ cache: 'no-store' }
);
return (await res.json()).map((post) => ({
slug: post.id.toString(),
}));
};
⚠️ 注意:
cache: 'no-store'会完全绕过 Next.js 缓存层,等效于传统 SSR 行为。若用于generateStaticParams,它仍会在构建时执行(因该函数仅在 build 时运行),但若你希望 页面内容 在每次访问时刷新,则必须同时在页面组件内使用no-store—— 这意味着你实际上放弃了 SSG,转为动态渲染(ISR/SSR)。请根据实际需求权衡。
✅ 方案二:设置自动重验证(推荐用于准实时、可容忍短暂延迟的内容)
使用 next: { revalidate } 指定缓存有效期(单位:秒),到期后自动后台更新:
const fetchPosts = async (params) => {
const res = await fetch(
`https://5875183d-18c0-49ad-b99d-8deeb4ded6a9.mock.pstmn.io/posts/${params.slug}`,
{ next: { revalidate: 30 } } // ← 30 秒后自动重新 fetch 并更新缓存
);
return res.json();
};
该方式兼具性能与新鲜度:首屏仍可命中缓存(快),后台静默更新(新),用户下次访问即获最新数据。适合博客、新闻、产品页等场景。
❌ 避免写法:链式 .then() + async/await 混用
你原代码中:
await fetch(...).then(...).then(...)
不仅冗余,还可能掩盖错误(如未处理 fetch 失败)。应统一使用 await 配合 try/catch:
const fetchPosts = async (params) => {
try {
const res = await fetch(
`https://.../posts/${params.slug}`,
{ next: { revalidate: 30 } }
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.error("Failed to fetch post:", err);
throw err;
}
};
总结
-
根本原因:Next.js 默认
force-cache使fetch结果固化于构建时; -
核心解法:主动声明缓存策略 ——
cache: 'no-store'(完全动态)或next: { revalidate: N }(增量更新); -
最佳实践:优先选用
revalidate实现 ISR(增量静态再生),兼顾速度与时效;仅当数据秒级变动且不可缓存时,才用no-store; - 额外提醒:Mock 服务(如 Postman Mock)本身无状态,确保其响应确已更新,避免误判为 Next.js 问题。
正确配置后,修改 mock 数据并刷新页面,即可立即看到 content: "test1 " 等最新内容。











