缓存导致版本不一致
场景
发布新版本后,部分用户还在访问旧版本,出现接口不兼容、样式错乱等问题。
分析思路
常见原因
根本解决方案
1. 正确的缓存策略
HTML → no-cache(每次请求协商)
JS/CSS/图片(带 hash) → max-age=31536000(强缓存一年)
Nginx 配置
# HTML 不缓存
location / {
add_header Cache-Control "no-cache, no-store, must-revalidate";
try_files $uri /index.html;
}
# 静态资源强缓存(文件名带 hash)
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
2. Service Worker 更新
SW 更新策略
// 注册时检查更新
navigator.serviceWorker.register('/sw.js').then((reg) => {
// 检测到新 SW 时提示用户
reg.addEventListener('updatefound', () => {
const newWorker = reg.installing!;
newWorker.addEventListener('statechange', () => {
if (newWorker.state === 'activated' && navigator.serviceWorker.controller) {
// 提示用户刷新
showUpdateNotification();
}
});
});
});
function showUpdateNotification() {
if (confirm('发现新版本,是否刷新?')) {
window.location.reload();
}
}
3. 版本检测与强制刷新
前端版本检测
// 构建时注入版本号
const APP_VERSION = __APP_VERSION__; // vite define
// 定时轮询版本
async function checkVersion() {
const res = await fetch('/version.json?t=' + Date.now());
const { version } = await res.json();
if (version !== APP_VERSION) {
showUpdateNotification();
}
}
setInterval(checkVersion, 5 * 60 * 1000); // 每 5 分钟检查
常见面试问题
Q1: 如何保证用户总是访问最新版本?
答案:
- HTML 不缓存:
Cache-Control: no-cache - 静态资源用 hash 文件名:内容变则 hash 变,URL 变则自动加载新版
- 部署时刷新 CDN 缓存
- 版本检测:前端轮询
version.json,发现新版本提示刷新 - Service Worker 要正确处理更新逻辑
Q2: 为什么不能对 HTML 设置强缓存?
答案:
HTML 是 SPA 的入口,里面包含对 JS/CSS 的引用(带 hash 文件名)。如果 HTML 被强缓存,新版本发布后用户还拿到旧 HTML,里面引用的是旧的 JS/CSS hash 文件名。如果旧文件被 CDN 清除了,就会 404 白屏。