Next.js 使用四种不同的缓存机制来优化性能,每种缓存都有不同的作用范围和生命周期。
单次渲染
跨请求持久化
构建时+运行时
客户端会话
| 特性 | Request Memoization | Data Cache | Full Route Cache | Router Cache |
|---|---|---|---|---|
| 存储位置 | 服务端内存 | 服务端文件系统 | 服务端文件系统 | 客户端内存 |
| 生命周期 | 单次渲染周期 | 持久化(直到重新验证) | 持久化(直到重新构建) | 30秒或用户会话 |
| 作用范围 | 同一渲染中的重复请求 | 所有 fetch 请求 | 整个路由/页面 | 客户端导航的路由 |
| 何时生效 | 自动(React 内置) | 默认所有 fetch | 静态路由(自动) | 客户端导航(自动) |
| 如何禁用 | ❌ 无法禁用 | cache: 'no-store' | dynamic = 'force-dynamic' | router.refresh() |
| 刷新页面 | 重置(新渲染周期) | 保持(使用缓存) | 保持(使用缓存) | 清空 |
| 重启服务器 | N/A | 保持(持久化) | 保持(持久化) | N/A(客户端) |
| 性能优势 | 减少重复请求 | 减少 API 调用 | 减少服务端渲染 | 加快客户端导航 |
客户端导航时首先检查
如果未命中客户端缓存,检查服务端预渲染的路由
如果需要渲染,检查 fetch 请求的缓存
同一渲染周期内去重重复请求
✅ 适用场景:
💡 最佳实践:
✅ 适用场景:
💡 最佳实践:
✅ 适用场景:
💡 最佳实践:
✅ 适用场景:
💡 最佳实践:
检查是否使用了 dynamic functions(cookies(), headers(), searchParams)或 cache: 'no-store'。这些会让页面变成动态渲染。
运行 pnpm build 查看输出:
○ /static-page ← 静态
λ /dynamic-page ← 动态
• 开发环境:删除 .next 目录并重启
• 生产环境:重新构建和部署
• 客户端:刷新浏览器或 router.refresh()
不完全一样。Full Route Cache 只在生产环境完全生效。 开发环境为了更好的开发体验,某些缓存行为会被修改。
查看哪些路由是静态的(○)、哪些是动态的(λ)
静态页面会有 .html 文件,动态页面只有 .js
在页面上显示渲染时间,刷新页面观察时间是否变化
在服务端代码中添加 console.log,查看执行次数
打开浏览器开发者工具,查看网络请求的数量和时间
查看组件的重新渲染情况