如何在 App Router 中通过 fetch 配置缓存策略(如 force-cache, no-store)来实现 SSG 或 SSR?
在 Next.js App Router 中,Next.js 扩展了原生的 Web fetch API。你可以通过在 fetch 函数的第二个参数中设置 cache 或 next 选项,来精确控制数据的缓存行为,从而实现 SSG(静态站点生成)、SSR(服务端渲染)或 ISR(增量静态再生)。
以下是具体的配置方法:
1. 实现 SSG (Static Site Generation) - 默认行为
SSG 意味着数据在 构建时 (Build Time) 获取,生成的 HTML 被缓存并在用户访问时复用。
- 配置策略:
force-cache(默认) - 适用场景: 博客文章、文档、营销页面等内容不经常变动的数据。
tsx
// app/page.tsx
async function getData() {
// 'force-cache' 是默认值,通常可以省略
// 这告诉 Next.js:在构建时获取数据并无限期缓存
const res = await fetch('https://api.example.com/data', {
cache: 'force-cache'
});
if (!res.ok) {
throw new Error('Failed to fetch data');
}
return res.json();
}
export default async function Page() {
const data = await getData();
return <main>{/* 使用 data 渲染 */}</main>;
}
2. 实现 SSR (Server-Side Rendering)
SSR 意味着数据在 每次请求时 (Request Time) 重新获取,HTML 是在服务器上为每个用户实时生成的。
- 配置策略:
no-store - 适用场景: 实时股票数据、用户个性化仪表盘、经常变化的数据。
tsx
// app/page.tsx
async function getData() {
// 'no-store' 告诉 Next.js:不要缓存这个请求
// 每次用户刷新页面,都会重新向 API 发起请求
const res = await fetch('https://api.example.com/data', {
cache: 'no-store'
});
return res.json();
}
export default async function Page() {
const data = await getData();
return <main>{/* 渲染实时数据 */}</main>;
}
3. 实现 ISR (Incremental Static Regeneration)
ISR 是 SSG 和 SSR 的混合体。页面在构建时生成,但在经过指定的时间(秒)后,如果有新请求进入,Next.js 会在后台重新验证并更新缓存。
- 配置策略:
next: { revalidate: <seconds> } - 适用场景: 电商产品列表(价格偶尔变动)、新闻列表。
tsx
// app/page.tsx
async function getData() {
// 设置 revalidate 为 60 秒
// 意味着数据会被缓存 60 秒。60秒后的第一个请求会触发后台更新。
const res = await fetch('https://api.example.com/data', {
next: { revalidate: 60 }
});
return res.json();
}
export default async function Page() {
const data = await getData();
return <main>{/* 渲染数据 */}</main>;
}
总结对比表
| 渲染模式 | fetch 配置 | 行为描述 | 适用场景 |
|---|---|---|---|
| SSG (静态) | { cache: 'force-cache' } (或省略) |
构建时获取,永久缓存。 | 博客、关于我们、帮助中心 |
| SSR (动态) | { cache: 'no-store' } |
每次请求时获取,不缓存。 | 实时数据、个性化内容 |
| ISR (增量) | { next: { revalidate: N } } |
缓存 N 秒,过期后后台更新。 | 产品详情、新闻流 |
补充:如果不使用 fetch (如直接查数据库)
如果你不使用 fetch (例如直接使用 Prisma 或 Mongoose 连接数据库),你无法使用上述参数。此时,你需要使用 Route Segment Config (路由段配置) 来控制页面的渲染策略。
在 layout.tsx 或 page.tsx 文件顶部导出以下变量:
强制 SSR (相当于 no-store):
tsx
export const dynamic = 'force-dynamic';
设置 ISR (相当于 revalidate):
tsx
export const revalidate = 60; // 每60秒重新验证
强制 SSG (默认):
tsx
export const dynamic = 'force-static';