按需失效实战

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

stale-while-revalidate:点击后本页立刻重取, 但拿到的仍是旧时间戳(旧值先回、后台重建); 再手动刷新一次,新时间戳才出现。

立即过期:只能在 Server Action 里调用; 点击后本页重取会等缓存重建完成, 响应里直接就是新时间戳(read-your-own-writes)。

预期观察:左按钮点击后本页立即重取,时间戳不变(旧值先回、后台重建),再刷新一次才变;右按钮点击后时间戳当场就变(读取方等重建完成)。 同一个标签、同一份产物,差异全部来自失效 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() 在请求时渲染, 或下沉为客户端取数

按需失效在缓存全景里的位置(它失效的是哪一层、客户端那层怎么办)见四层缓存对照台; 「一个页面该选时间窗口还是标签失效」的完整决策流程见缓存策略专题。