Vue<前端页面版本检测>
2026年2月1日 14:13
为什么需要版本检测
1. 解决浏览器缓存问题
- 静态资源缓存:浏览器会缓存 JS、CSS 等静态资源,用户可能继续使用旧版本
- 用户体验影响:用户无法及时获取新功能,导致功能缺失或操作异常
2. 保障功能一致性
- 功能同步:确保所有用户都能使用最新的功能和修复
- 数据一致性:避免因版本差异导致的数据不一致问题
3. 提升用户体验
- 主动提醒:在新版本发布后主动通知用户更新
- 无缝升级:减少用户手动刷新页面的需求
版本检测核心思路
![]()
整体架构
构建阶段 → 版本文件生成 → 运行时检测 → 版本对比 → 用户提醒
技术实现要点
1. 版本标识生成
- 构建时生成:每次打包时生成唯一的版本标识
- 时间戳方案:使用时间戳确保每次构建版本号唯一
2. 版本文件部署
-
JSON 格式:将版本信息保存为
version.json文件 - 静态访问:通过 HTTP 请求可直接访问版本文件
3. 客户端检测机制
- 定时轮询:定期检查服务器版本文件
- 版本对比:比较本地缓存版本与服务器版本
- 智能提醒:仅在版本不一致时提醒用户
版本检测实现步骤
步骤一:构建版本文件生成脚本
创建 build-version.js 文件:
// build-version.js (自动生成版本文件脚本)
const fs = require('fs')
const path = require('path')
// 方案A:使用时间戳作为版本标识(最简单,确保每次打包唯一)
const version = new Date().getTime().toString()
// 版本文件内容
const versionJson = {
version: version,
updateTime: new Date().toLocaleString() // 可选:添加更新时间,便于排查
}
// 写入version.json文件(项目根目录)
const versionPath = path.resolve(__dirname, 'public', 'version.json')
fs.writeFileSync(versionPath, JSON.stringify(versionJson, null, 2), 'utf-8')
console.log(`✅ 自动生成版本文件成功,版本号:${version}`)
步骤二:修改构建命令
在 package.json 中修改构建命令:
{
"scripts": {
"build:prod": "node build-version.js && vue-cli-service build"
}
}
步骤三:配置 Vue 构建过程
在 vue.config.js 中添加版本文件复制配置:
chainWebpack(config) {
// ... 其他配置
// 复制 version.json 到 dist 目录
config.plugin('copy')
.tap(args => {
const hasVersionJson = args[0].some(item => item.from === 'version.json')
if (!hasVersionJson) {
args[0].push({
from: path.resolve(__dirname, 'public/version.json'),
to: path.resolve(__dirname, 'dist/version.json')
})
}
return args
})
}
步骤四:实现版本检测工具类
创建 src/utils/versionUpdate.js:
// src/utils/versionUpdate.js
import { Notification } from 'element-ui'
/**
* 版本更新检测工具类(仅生产环境启用轮询,内置环境判断)
*/
class VersionUpdate {
constructor(options = {}) {
this.config = {
versionFileUrl: '/version.json', // 版本文件地址
localVersionKey: 'cmpVersion', // 本地存储的版本号key
disableFetchCache: true, // 禁用Fetch缓存
pollInterval: 5 * 60 * 1000, // 5分钟轮询一次
hasNotified: false // 是否已提醒过用户有新版本
}
Object.assign(this.config, options)
// 定时轮询定时器
this.pollTimer = null
// 识别当前环境(Vue CLI 4 自动注入的环境变量)
this.isProduction = process.env.NODE_ENV === 'production'
}
/**
* 核心方法:执行版本检测
*/
async checkVersion(isInit = false) {
try {
if (this.config.hasNotified) return false
const localVersion = localStorage.getItem(this.config.localVersionKey) || ''
const fetchOptions = {}
if (this.config.disableFetchCache) {
fetchOptions.cache = 'no-cache'
}
const response = await fetch(this.config.versionFileUrl, fetchOptions)
if (!response.ok) {
throw new Error(`版本文件请求失败,状态码:${response.status}`)
}
const latestVersionInfo = await response.json()
const serverVersion = latestVersionInfo.version
if (isInit) {
this.cacheLatestVersion(serverVersion)
return true
}
if (serverVersion && serverVersion !== localVersion) {
this.config.hasNotified = true
console.log('有新版本可用', latestVersionInfo)
Notification({
title: '🎉 有新版本可用',
dangerouslyUseHTMLString: true,
message: `<p style="font-size:12px;">建议点击刷新页面,以获取最新功能和修复</p> <p style="color:#cccccc;font-size:12px;">更新时间:${latestVersionInfo.updateTime}</p>`,
duration: 0,
customClass: 'check-version-notify',
onClick: () => {
this.forceRefreshPage()
},
onClose: () => {
this.resetNotifyFlag()
}
})
return true
} else {
// 版本一致时,重置提醒标记,便于后续轮询检测新版本
this.config.hasNotified = false
// console.log('当前已是最新版本,已缓存最新版本号')
return false
}
} catch (error) {
console.warn('版本检测异常,不影响应用运行:', error.message)
return false
}
}
/**
* 启动定时轮询检测(内置环境判断:仅生产环境生效)
*/
async startPolling() {
// 核心:非生产环境,直接返回,不启动轮询
if (!this.isProduction) {
console.log('当前为非生产环境,不启动版本检测轮询')
return
}
// 生产环境:正常启动轮询
this.stopPolling() // 先停止已有轮询,避免重复启动
this.checkVersion(true) // 立即执行一次检测
this.pollTimer = setInterval(() => {
this.checkVersion()
}, this.config.pollInterval)
console.log(`生产环境版本轮询检测已启动,每隔${this.config.pollInterval / 1000 / 60}分钟检测一次`)
}
/**
* 停止定时轮询检测
*/
stopPolling() {
if (this.pollTimer) {
clearInterval(this.pollTimer)
this.pollTimer = null
console.log('版本轮询检测已停止')
}
}
/**
* 重置提醒标记
*/
resetNotifyFlag() {
this.config.hasNotified = false
}
// 缓存最新版本号
cacheLatestVersion(version) {
localStorage.setItem(this.config.localVersionKey, version)
this.resetNotifyFlag()
}
// 强制刷新页面
forceRefreshPage() {
window.location.reload(true)
}
}
const versionUpdateInstance = new VersionUpdate()
export { VersionUpdate, versionUpdateInstance }
export default versionUpdateInstance
创建自定义.check-version-notify的版本检测全局样式:
![]()
// 版本检测通知样式
.check-version-notify{
border: 3px solid transparent !important;
cursor: pointer;
background-color: rgba(255, 255, 255, 0.6) !important;
backdrop-filter: blur(5px);
&:hover{
border: 3px solid $--color-primary !important;
}
.el-notification__icon{
font-size: 18px;
height: 18px;
}
.el-notification__title{
font-size: 14px;
line-height: 18px;
}
.el-notification__group{
margin-left: 8px;
}
}
步骤五:在应用入口启动版本检测
在 App.vue 或合适的入口文件中启动版本检测:
import versionUpdate from '@/utils/versionUpdate'
...
mounted() {
versionUpdate.startPolling()
},
beforeDestroy() {
versionUpdate.stopPolling()
}