前端版本发布后浏览器需要手动刷新问题解决

401 阅读2分钟

项目技术栈: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"

这是第一次写博客,有不好的地方请各位大佬指出,谢谢!