前言
前端项目发布新版本后,若用户已打开页面或浏览器挂在后台,由于单页应用 (SPA) 的机制,页面不会主动刷新,导致用户一直停留在旧版本,无法使用新功能或遇到已修复的 Bug
那在开发过程中很容易遇到过这种问题,当我把前端写好的新版本的代码进行打包上传,这个动作已经进行了版本更新了,但是用户在访问旧版本网页时如果没有点击刷新,根本不知道已经上新了新版本,而且如果新版本已经取消了某个功能,但用户用旧版本进行提交必然会出错
那么就需要一个主动检测版本更新的功能提醒用户更新了
效果

实现过程
-
构建阶段:在打包时生成一个包含当前时间戳的唯一版本标识文件 (version.json)。
-
部署阶段:Nginx 配置该文件禁止缓存,确保前端永远获取到最新状态。
-
运行阶段:前端代码通过轮询和页面可见性检测,对比本地与服务器的版本号。
实现逻辑如下

构建脚本改造 (生成版本号)
我们需要在每次 npm run build 时,在输出目录(通常是 dist 或 public)生成一个 version.json。
在项目根目录新建脚本文件 generate-version.js:
js
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
// 获取当前模块的路径
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 定义版本号
const versionInfo = {
version: Date.now(),
releaseTime: new Date().toLocaleString()
};
// 确定输出路径
const outputDir = path.join(__dirname, 'public');
// 先写入 public 目录,打包时会自动复制到 dist
const filePath = path.join(outputDir, 'version.json');
// 写入文件
fs.writeFileSync(filePath, JSON.stringify(versionInfo, null, 2));
console.log(`✅ [Version] 版本文件已生成: ${filePath}`);
console.log(`✅ [Version] 当前版本标识: ${versionInfo.version}`);
前端自动检测逻辑
在项目的主入口文件(如 src/App.vue, src/App.jsx, src/main.js)中引入以下逻辑。
js
/**
* 前端版本自动检测模块
*/
// 存储本地版本号
let localHash:any = null;
// 检测间隔 (毫秒),建议 60秒 或 5分钟
const CHECK_INTERVAL = 5 * 1000;
async function checkAppVersion() {
try {
// 1. 请求 version.json
// 必须加上时间戳参数 t=... 防止浏览器缓存这个 GET 请求本身
const res = await fetch(`/version.json?t=${Date.now()}`);
if (!res.ok) throw new Error('Version file not found');
const data = await res.json();
const serverHash = data.version;
// 2. 首次加载,只记录不比对
if (!localHash) {
localHash = serverHash;
console.log(`-----------------------[Updater] 当前版本已锁定-----------------------: ${localHash}`);
return;
}
// 3. 比对版本
if (serverHash !== localHash) {
console.log(`-----------------[Updater] 检测到新版本------------------------: ${serverHash} (当前: ${localHash})`);
showUpdateNotification();
}
console.log(`----------------------[Test] 执行检测-----------------------: ${localHash}`);
} catch (err) {
// 静默失败,不打扰用户 (可能是网络波动)
console.warn('---------------------[Updater] 版本检测失败:--------------------------', err);
}
}
function showUpdateNotification() {
import('element-plus').then(({ ElMessageBox }) => {
ElMessageBox.confirm(
'系统检测到有新版本发布,请点击"确定"刷新页面以获取最新功能。',
'版本更新提示',
{
confirmButtonText: '立即刷新',
cancelButtonText: '稍后再说',
type: 'warning',
center: true,
modal: false
}
).then(() => {
window.location.reload(true); // true 表示强制从服务器重载
}).catch(() => {
// 用户点击取消,不做任何操作
});
});
}
// --- 启动检测监听 ---
// 1. 启动定时轮询
setInterval(checkAppVersion, CHECK_INTERVAL);
// 2. 智能监听:当用户切换标签页回来时,立即检查一次
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
checkAppVersion();
}
});
// 3. 初始化检查
checkAppVersion();
修改 package.json:
