字
字节笔记本
2026年5月3日
TanStack Start - ISR 增量静态再生成
API中转
¥120
从 CDN 提供静态生成的内容,同时在后台定期重新生成。ISR 给你静态网站的性能优势,同时保持动态内容的新鲜度。TanStack Start 的 ISR 方法利用与任何 CDN 兼容的标准 HTTP 缓存头。
什么是 ISR
增量静态再生成(ISR)允许你从 CDN 提供静态生成的内容,同时在后台定期重新生成。核心概念:
- 静态预渲染: 页面在构建时生成
- CDN 缓存: 缓存头控制 CDN 缓存 HTML 的时间
- 重新验证: 缓存过期后,下一个请求触发重新生成
- Stale-While-Revalidate: 在后台获取新数据时提供过期内容
缓存头策略
使用带有 max-age 和 s-maxage 指令的 Cache-Control 头:
tsx
// routes/blog/posts/$postId.tsx
export const Route = createFileRoute('/blog/posts/$postId')({
loader: async ({ params }) => {
const post = await fetchPost(params.postId)
return { post }
},
headers: () => ({
'Cache-Control':
'public, max-age=3600, s-maxage=3600, stale-while-revalidate=86400',
}),
})Cache-Control 指令
| 指令 | 描述 |
|---|---|
public | 响应可以被任何缓存缓存 |
max-age=3600 | 内容在 3600 秒内是新鲜的 |
s-maxage=3600 | 覆盖共享缓存(CDN)的 max-age |
stale-while-revalidate=86400 | 在后台重新验证时提供过期内容最多 24 小时 |
immutable | 内容永远不会更改 |
与服务端函数的 ISR
服务端函数也可以设置缓存头:
tsx
// routes/api/products/$productId.ts
export const Route = createFileRoute('/api/products/$productId')({
server: {
handlers: {
GET: async ({ params }) => {
const product = await db.products.findById(params.productId)
return Response.json(
{ product },
{
headers: {
'Cache-Control': 'public, max-age=300, stale-while-revalidate=600',
'CDN-Cache-Control': 'max-age=3600',
},
},
)
},
},
},
})按需重新验证
通过 CDN 的 API 触发缓存清除:
tsx
// routes/api/revalidate.ts
export const Route = createFileRoute('/api/revalidate')({
server: {
handlers: {
POST: async ({ request }) => {
const { path, secret } = await request.json()
if (secret !== process.env.REVALIDATE_SECRET) {
return Response.json({ error: 'Invalid token' }, { status: 401 })
}
await fetch(
`https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/purge_cache`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${CF_API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ files: [`https://yoursite.com${path}`] }),
},
)
return Response.json({ revalidated: true })
},
},
},
})CDN 特定配置
| CDN | 特定头 | 用途 |
|---|---|---|
| Cloudflare | CDN-Cache-Control | 更精细的 CDN 控制 |
| Netlify | _headers 文件 | 静态配置 |
| Vercel | s-maxage | Edge Network 优化 |
与客户端缓存结合
TanStack Router 的内置缓存控制与 CDN 缓存配合使用:
tsx
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => fetchPost(params.postId),
headers: () => ({
'Cache-Control': 'public, max-age=3600, stale-while-revalidate=86400',
}),
staleTime: 60_000, // 客户端上数据保持新鲜 60 秒
gcTime: 5 * 60_000, // 在内存中保留 5 分钟
})常见 ISR 模式
| 内容类型 | max-age | stale-while-revalidate | staleTime |
|---|---|---|---|
| 博客文章 | 3600s (1h) | 604800s (7d) | 300s (5m) |
| 产品页面 | 300s (5m) | 3600s (1h) | 30s |
| 落地页 | 86400s (1d) | 604800s (7d) | 3600s (1h) |
| 用户数据 | 60s | 0 | 30s |
缓存头速查
| 指令 | 用途 | 值示例 |
|---|---|---|
public | 允许 CDN 缓存 | - |
private | 仅浏览器缓存 | - |
max-age | 新鲜时间 | 3600 (1h) |
s-maxage | CDN 覆盖 | 7200 (2h) |
stale-while-revalidate | 后台重新验证 | 86400 (1d) |
分享: