跳到主要内容

缓存导致版本不一致

场景

发布新版本后,部分用户还在访问旧版本,出现接口不兼容、样式错乱等问题。

分析思路

常见原因

根本解决方案

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: 如何保证用户总是访问最新版本?

答案

  1. HTML 不缓存Cache-Control: no-cache
  2. 静态资源用 hash 文件名:内容变则 hash 变,URL 变则自动加载新版
  3. 部署时刷新 CDN 缓存
  4. 版本检测:前端轮询 version.json,发现新版本提示刷新
  5. Service Worker 要正确处理更新逻辑

Q2: 为什么不能对 HTML 设置强缓存?

答案

HTML 是 SPA 的入口,里面包含对 JS/CSS 的引用(带 hash 文件名)。如果 HTML 被强缓存,新版本发布后用户还拿到旧 HTML,里面引用的是旧的 JS/CSS hash 文件名。如果旧文件被 CDN 清除了,就会 404 白屏。

相关链接