缓存导致版本不一致
场景
发布新版本后,部分用户还在访问旧版本,出现接口不兼容、样式错乱等问题。
面试速答版
版本不一致 / 用户拿到旧版怎么解决? 核心是 HTML 不缓存、静态资源带 hash 强缓存:
- 文件名带 hash →
Cache-Control: max-age=31536000, immutable,长期复用。 - HTML 用
no-cache,每次发请求协商,确保拿到最新引用。 - Service Worker 监听
updatefound,弹提示让用户刷新。 - 旧资源 chunk 要保留一段时间,否则切版本会
ChunkLoadError。 - 发布后刷新 CDN 缓存,或用版本目录隔离
/v1.2.3/...。
分析思路
常见原因
根本解决方案
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 白屏。