按需失效实战
cacheTag 打标 + revalidateTag/updateTag 精准唤醒:SWR 与立即过期两种语义在同一份缓存产物上对照,tag 与 path 的失效粒度选择
活演示:同一份缓存,两种失效语义
这份产物用 cacheLife("max") 冻结了时间窗口 —— 时间戳不变是特性;它只认 cacheTag,点击按钮后再刷新观察
缓存产物生成时刻(UTC)· 标签 revalidation-posts
2026-11-09T08:20:40.830Z
- #1 sunt aut facere repellat provident occaecati excepturi optio reprehenderit
- #2 qui est esse
- #3 ea molestias quasi exercitationem repellat qui ipsa sit aut
预期观察:左按钮点击后本页立即重取,时间戳不变(旧值先回、后台重建),再刷新一次才变;右按钮点击后时间戳当场就变(读取方等重建完成)。 同一个标签、同一份产物,差异全部来自失效 API 的语义。
四个失效/刷新 API 的分工
不是四个可互换的开关:调在哪、影响哪一层、读取方等不等,各不相同
| API | 调用位置 | 语义 | 典型场景 |
|---|---|---|---|
| updateTag(tag) | 仅 Server Action | 立即过期;下一次读取等新值(read-your-own-writes) | 本页表单改了数据,响应里就要带新值 |
| revalidateTag(tag, profile) | Server Action / Route Handler | 标过期;下次读取先回旧值、后台重建(SWR) | CMS webhook、定时任务 —— 读者晚几秒看到无所谓 |
| revalidatePath(path) | Server Action / Route Handler | 按路径失效:该路由渲染涉及的缓存条目全部作废旧值(SWR) | 留言板式变更:只知道「这页该重渲」,不记得打过什么标 |
| refresh() | 仅 Server Action | 不动服务端缓存;让客户端路由重取当前页(清客户端侧缓存) | 改了 cookie/会话等「不进缓存标签」的请求时数据,要立刻回读 |
cacheComponents 下的一个变化:Server Action 执行完不再自动重渲当前路由 —— 想让用户立刻看到变更,action 里要显式 revalidatePath / refresh (本页两个 action 末尾的 refresh() 就是这个作用)。
tag vs path:失效粒度怎么选
tag 的波及面由打标决定,path 的波及面由路由决定;选错了要么漏失效,要么误伤
// 按标签失效:精准命中「这类数据」,波及面由打标决定
async function getPosts() {
"use cache";
cacheTag("posts"); // 这份产物贴上 posts 标签
return db.posts.findMany();
}
// 任意 action 里:只失效贴了 "posts" 的条目,别的缓存不动
updateTag("posts");
// 按路径失效:命中「这条路渲染时用到的所有缓存」,波及面由路由决定
revalidatePath("/data/revalidation");
// 该路径渲染涉及的缓存条目全部失效 —— 粗,但不需要你记得打过什么标
// 选择依据:
// 知道「哪类数据变了」→ tag(变更发生在数据源,如 CMS webhook)
// 只知道「这个页面该重渲了」→ path(变更发生在本页表单,如留言板)本页的标签刻意独立命名为revalidation-posts而不是复用 /rendering/isr 的"posts":cacheTag 是全局命名空间,共用标签意味着共用失效 —— 这里的按钮会把 ISR 页的缓存一起打掉。标签设计就是失效波及面设计。
什么时候别用 tags & 继续深入
按需失效的前提是「变更有人通知你」;没有这个前提,标签只是摆设
- 低频且没人通知变更的数据,直接别缓存:tags 适合 「源站变更能触发回调(webhook、后台任务)」的数据;如果变更只有你 自己知道,一个简单的 cacheLife 时间窗口比维护标签体系省心得多
- 高变更频率数据别用 tag 失效硬撑:失效重建也是成本, 每分钟都在变的数据,缓存命中率趋近于零,回到默认动态渲染
- 按人不同的数据进不了这套体系:tags 失效的是 「所有人共享的一份」,会话相关数据用 cookies() 在请求时渲染, 或下沉为客户端取数
按需失效在缓存全景里的位置(它失效的是哪一层、客户端那层怎么办)见四层缓存对照台; 「一个页面该选时间窗口还是标签失效」的完整决策流程见缓存策略专题。