·更新于 2026年10月25日· 16 次浏览 Nuxt 3Vue 3SSRRedis缓存BUG复盘

Nuxt 3 缓存别把登录态混进去:我把页面拆成匿名壳和用户态片段

一次游客看到别人昵称的 BUG,让我意识到 SSR 缓存不能只按 URL 存。于是把公共内容做成匿名壳,把用户态拆到组件级请求,用 Redis 键分组隔离。

Nuxt 3 缓存别把登录态混进去:我把页面拆成匿名壳和用户态片段 封面
ZHOUYI

作者

ZHOUYI

线上有用户反馈:未登录打开首页,居然看到了“欢迎你,某某”。第一反应是见鬼了,查下去发现是 SSR 页面缓存把登录用户的 HTML 存了下来,下一个游客请求同一个 URL 时直接命中。问题根因很简单:缓存键只看了路径和参数,没区分访问者身份。

先把缓存键从 URL 改成匿名分组

我一开始想按 userId 拆缓存,但这样命中率会掉得很厉害。更稳的做法是分成两层:匿名公共内容可以共享缓存;登录态内容要么不缓存,要么只按用户短缓存。判断依据是请求里有没有会话 Cookie,但 Redis key 里不直接放敏感信息,只放 anon 或 auth 这种分组。

js
const hasSession = Boolean(cookieHeader?.includes('sid='))
const group = hasSession ? 'auth' : 'anon'
const key = `page:${pathname}:${group}`
if (group === 'auth') {
  return renderNoStore()
}
const html = await redis.get(key)
if (html) return html

用户态不进壳,组件级再取

页面级 HTML 只保留公共内容:文章正文、列表、SEO 标题、结构化描述。导航栏昵称、收藏状态、未读消息这些,全部放到组件级请求里再取。这样游客拿到的是可缓存的匿名壳,登录用户进来后,前端组件再补上私有片段,避免整页 HTML 被串号。

  • 公共内容:按 URL + anon 分组缓存
  • 用户态:按会话短缓存,或直接 no-store
  • 组件级请求单独控制缓存,避免被页面缓存吞掉

踩坑:Cookie 分组要和缓存策略一致

最开始我只在服务端读了 Cookie 分组,但上层代理和 CDN 并不知道这个差异,导致仍有可能缓存错内容。后来我把规则统一:只要命中 auth 分组,响应就明确不缓存;只有 anon 分组才允许进入 Redis 或 CDN。涉及具体响应头和缓存策略,建议以官方文档为准。

“SSR 缓存最怕的不是慢,而是把“你的页面”错发给“他”。”

改造后,首页和文章页依旧能吃满 Redis 缓存,但登录昵称、个人状态不再进入公共 HTML。这个方案不复杂,核心就三件事:缓存键区分匿名与登录、页面壳只放公共内容、用户态交给组件级请求。遇到类似 BUG,先问自己:这页有没有私有数据?缓存键有没有区分身份?用户态是不是被提前渲染进去了?

Guestbook

留言

若这篇文章也曾停在你心上,留一行字吧,我会看的。

先确认一下邮箱

多这一步,是为了少些机器骚扰,也让我能更踏实地读每一条真人写下的字。验证码 10 分钟内有效;同一邮箱 60 秒内只能发一封。

本文留言

共 0 条已加载 0 条

这里还静悄悄的——愿意做第一个留下脚印的人吗?