📘 背景说明
在多环境架构中(如 测试环境 / 灰度环境 / 正式环境),用户登录后后端会返回一个 version(例如:legacy, gray, online),前端将其写入 Cookie 中。
页面通过 DCDN 加速资源 ,DCDN 根据 version 判断应该回源到哪个环境。
然而,当 version 改变后刷新页面时,浏览器或 DCDN 返回 304 Not Modified 状态,导致资源仍然加载旧环境缓存,从而界面未更新。
🧩 问题原因分析
1. 浏览器缓存行为
304 表示:
"资源未修改,客户端使用本地缓存版本。"
浏览器判断是否返回304的依据是:
- 请求头中的
If-None-Match(Etag 对比) - 或
If-Modified-Since(时间对比)
所以,即使 version 已经变了,只要 URL 相同、Etag 相同,浏览器仍会使用旧缓存。
2. DCDN 缓存行为
DCDN(例如阿里云、腾讯云、Cloudflare等)默认根据以下内容决定缓存唯一性:
- URL(含 query 参数)
- 请求方法(GET/POST)
- 有时还包括头部(如 Host)
但不会自动感知 Cookie 变化 ,除非你手动配置 自定义 Cache Key。
因此,当 version 变化后,DCDN 仍会命中旧缓存资源。
✅ 解决方案总览
| 目标 | 方案 | 难度 |
|---|---|---|
| ✅ 不同环境返回不同缓存 | 自定义 DCDN Cache Key ,加入 version |
★★★★ |
| ✅ 立即刷新资源 | 强制跳过浏览器缓存(版本号/时间戳参数) | ★★ |
| ✅ 代码自动判断 version 变化 | 检测 cookie 变化 → 强制 reload | ★★ |
🧠 实施步骤详解
🧩 步骤 1:后端返回 version 并写入 Cookie
plain
// 登录成功后
res.cookie('version', user.version, {
httpOnly: false,
path: '/',
sameSite: 'Lax'
});
或者前端设置:
plain
document.cookie = `version=${version}; path=/;`;
🧩 步骤 2:DCDN 配置自定义 Cache Key
🔧 不同云厂商的配置略有不同,以下以 阿里云 DCDN 为例。
操作路径
阿里云控制台 → DCDN → 域名管理 → 缓存配置 → 自定义 Cache Key
配置规则
在 Cache Key 中添加 Cookie 字段:
plain
CacheKey = ${uri}?v=${cookie:version}
或更通用写法:
plain
CacheKey = ${uri}_${cookie.version}
效果
当用户的 version 改变时,DCDN 会生成不同的缓存 Key,从而回源获取对应环境的新资源。
🧩 步骤 3:浏览器缓存控制(可选优化)
为避免浏览器本地缓存干扰,可以在 HTTP 响应头中加:
plain
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
或仅针对关键页面(如 index.html)生效。
🧩 步骤 4:前端刷新策略(增强版)
为了防止 Cookie 变化后浏览器仍使用旧资源,可以检测 version 是否变化:
plain
// utils/version.ts
export function checkVersionChange() {
const current = document.cookie.match(/version=([^;]+)/)?.[1];
const stored = localStorage.getItem('last_version');
if (current && current !== stored) {
localStorage.setItem('last_version', current);
// 强制刷新一次,确保加载新资源
location.reload(true);
}
}
在 _app.tsx 或入口组件中执行:
plain
useEffect(() => {
checkVersionChange();
}, []);
🧩 步骤 5:调试验证
✅ 验证 304 问题是否解决
- 打开浏览器控制台 → Network
- 登录后查看 Cookie → version 是否变化
- 刷新页面,查看资源请求状态:
- 若 DCDN 命中新缓存,状态为 200
- 若仍是 304,说明浏览器或 CDN 仍在使用旧缓存,需要检查 CacheKey 或响应头
🧰 最佳实践建议
| 场景 | 建议 |
|---|---|
| 前端资源通过 DCDN 分发 | 配置 自定义 CacheKey ,加入 version |
| 用户登录后切换环境 | 触发一次强制 reload |
| index.html 文件 | 设置 Cache-Control: no-cache |
| 静态资源(js/css) | 允许缓存,但打包时带上 hash(例如 main.[hash].js ) |
🏁 总结
| 问题 | 原因 | 解决方式 |
|---|---|---|
| version 变化但页面不变 | 浏览器/DCDN 缓存命中 | 自定义 CacheKey + 强制刷新 |
| 页面 304 返回旧内容 | 浏览器使用旧缓存 | 添加 Cache-Control 头或 reload |
| DCDN 不识别 Cookie | CacheKey 未配置 | 加入 ${cookie.version} |
📄 示例配置总结
阿里云 DCDN 示例:
plain
CacheKey:
${uri}_${cookie.version}
Cache TTL:
HTML: 0s
JS/CSS: 3600s
响应头示例:
plain
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: text/html