项目技术栈:Vue2+element-ui
问题场景:当前端打包发布后,浏览器是感知不到的,需要用户手动刷新浏览器才能获取最新代码 我也在AI和网上搜索过一些文章,但是处理方案都不是很完美,以下是俩个痛点
1.时间戳作为版本号
这是最常规的做法,但是会引发一个问题,就是代码如果没有做任何改变,这时候发布了新版本,还是会提醒用户发布了新版本,但其实没有做出更新
2.将版本号存入localstorage与最新版本号进行对比
当用户手动刷新浏览器,这时候如果版本更新了,会提醒用户再次刷新浏览器,造成了多余动作
话不多说,以下是我的解决方案
main.js
页面加载触发一次,之后每20分钟触发一次
imoort { isNewVersion } from '@/utils/version.js'
if(process.env.NODE_ENV === 'production') {
isNewVersion()
setInterval(isNewVersion, 1000 * 60 * 20)
}
@/utils/version.js
import axios from 'axios'
import Vue from 'vue'
// name是我们项目模块名,可以不带,不带的话后续代码要做出对应调整
const { name } = require('../../package.json')
function extractAndconcatContent(inputString){
let match;
let result = '';
// 正则匹配js文件和css文件的hash值,拼接成字符串
const regex =/(chunk-vendors|app)\.([\da-fA-F]+)\.(js|css)g;
while((match=regex.exec(inputstring)) !== null) {
//提取捕获组中的内容(即中间部分)
const content = match[2];
result += content;// 拼接内容
}
return result;
}
export async function isNewersion() {
const url = `//${window.location.host}/${name}/static/version.json`
try {
// 获取version.json值
const res = await axios.get(url,{ headers:{ 'Cache-control': 'no-cache' } })
const newVersion =String(res.data[`${name}-version`])
// 获取当前网页拼接的hash值
const localVersion = extractAndconcatContent(document.documentElement.innerHTML)
// 进行对比,若是不同则提示刷新网页
if (localVersion !== newVersion) {
Vue.prototype.$confirm('当前模块有新版本发布,请刷新页面', '提示', {
confirmButonText:'确定',
type:'warning',
showClose: false,
showCancelButton: false,
closeOnclickModel:false,
})then(()=>
window,location.reload()
})
}
} catch (error) {
console.log('获取线上版本号失败utils/version.js', errer)
}
@/utils/generateVersionJson.js
此文件作用:在项目打包完成后获取index.html文件,把index.html的js文件和css文件的hash值拼接成字符串,保存到生成的version.json文件,后续通过axios请求获取该值
const fs = require('fs')
const path = require('path')
const { name } = require('../../package.json')
const htmlFile = './dist/index.html'
function extractAndconcatcontent(inputstring) {
const regex = /(chunk-vendors|app).([\da-fA-F]+).(js|css)/g:
let match;
let result = '';
while((match = regex.exec(inputstring)) !== null) {
// 提取捕获组中的内容(即中间部分)
const content = match[2l;
result += content; // 拼接内容
return result;
if(fs.existsSync(htmlFile)) {
const content = fs.readFileSync(htmlFile, 'utf-8' )
// 定义要写入的 JSON 数据
const versionData = { [`${name}-version`]: extractAndConcatContent(content) }
// 定义输出文件路径(假设构建输出目录是 dist)
const outputPath = path.join(dirname, '..', '..', 'dist/static', 'version.json')
// 写入JSON 文件
fs.writeFile(outputPath, JSON.stringify(versionData, null, 2), (err) => {
if(err) {
console.error('Error writing version.json', err)
return
}
console.log('version.json has been created successfully.')
})
} else {
console.error('index.html未找到')
process.exit(1)
}
package.json
postbuild为内置钩子,build执行之后会自动执行
"build": "vue-cli-service build",
"postbuild": "node src/utils/generateVersionJson.js"
这是第一次写博客,有不好的地方请各位大佬指出,谢谢!