vue自动清除缓存, 打包发版后,客户端页面自动更新

一:需求
页面打包上传到服务器后,用户能在自己电脑上立即感知到更新
二:需求分析
调研后得知:
1.靠浏览器缓存,各种catche啥的不靠谱. -----pass,缓存不会那么快生效
2.页面JS定时去查询服务器保存版本号的文件,查看版本号是否过期
---pass,效率太差,如果有十万用户,每个用户五分钟去服务器查询一次,服务器每
五分钟被查询五十万次.

三:实现方案
前端接口请求http-header 携带时间戳版本号,后端比对时间戳版本号.
如果请求带过来的时间戳小于服务器保存的,返回版本号过期错误.

如果请求带过来的时间戳大于服务器保存的时间戳,更新服务器时间戳版本号.
同时,如果请求没带版本号参数,则不对版本号进行校验,方便dev环境前端开发.
前端最好能自动生成版本号,自动更新,不用手动填值.

如果版本号过旧就执行JS代码location.reload(true),但是上线后有的人的浏览器
执行了location.reload(true) 或者ctrl+f5,有可能部分文件还是走的缓存.

所以弹窗让用户选择更新还是取消.如果选取消就清空版本号,后端不校验空的就行

四:具体代码应用
样例代码为vue2+webpack. 主要都是JS代码. vue3和react也可以参考

第一步修改 入口文件

在入口文件index.html创建一个同级别JS文件config.js
在index.html引入这个文件

 <script src="config.js?version=123456789"></script>
image.png

index.html引入文件后面有个后缀?version=123456789,为什么要带这个后缀呢?
因为不带部分浏览器会给你缓存了,哪怕用户ctrl+f5也不行,只能手动清理缓存.
这个后缀的数字123456789每次打包后都会被修改,为了方便就修改成版本号

第二步 创建config.js

代码如下,里面代码不重要,主要起到模板记录作用,因为每次打包会重新生成.
主要意思就是读取版本号变量timestamp 的值,并存入localStorage中,
这样接口请求的时候可以从localStorage读取timestamp 的值放到head带给后端.

 let timestamp = 1693386173000


        if(localStorage.timestamp){
          if(timestamp < localStorage.timestamp){
            console.log('timestamp is small')
          }else{
            console.log('timestamp is big')
            localStorage.timestamp = timestamp
          }
        }else{
          localStorage.timestamp = timestamp
        }
      
console.log('configjs read again')

上面代码除了注释可以删,每一行都有用,谨慎修改
3.修改vue.config.js
我们要在输入npm run build打包命令后,进行操作

引入node的文件函数,能读取文件

const fs = require("fs");
// 判断是否为生产环境
const isProd = process.env.NODE_ENV === "production";

然后在plugins下面放入同级函数

const Timestamp = new Date().getTime(); //时间戳
if (isProd) {

  fs.readFile("./public/config.js", "utf8", function(err, data) {
    if (err) {
      console.log(err)
      return
    }
    // console.log(data)
    try {
      //   data = data.replace('1693971026219',Timestamp)
      data = "";
      let c_1 = " let timestamp = " + Timestamp;
      console.log("c_1", c_1);
      data = c_1 + "\n" + data;

      let c_3 = "\n"+"console.log('configjs read again')"

      let c_4 = `
        if(localStorage.timestamp){
          if(timestamp < localStorage.timestamp){
            console.log('timestamp is small')
          }else{
            console.log('timestamp is big')
            localStorage.timestamp = timestamp
          }
        }else{
          localStorage.timestamp = timestamp
        }
      `
  
      data = data +"\n"+String(c_4)  + c_3
      console.log('result_data',data)
    } catch (err2) {
      console.log(err2);
    }
  
    fs.writeFile("./public/config.js", data, function(err) {
      if (err) {
        console.log(err)
      }
      console.log("configjs文件已修改");
    });
  });


  fs.readFile("./public/index.html", "utf8", function(err, data_2) {
    if (err) {
      console.log(err)
      return
    }
    // console.log(data)
    try {
         data_2 = data_2.replace('123456789',Timestamp)
     
    } catch (err2) {
      console.log(err2);
    }
  
    fs.writeFile("./public/index.html", data_2, function(err) {
      if (err) {
        console.log(err)
      }
      console.log("html文件已修改");
     // console.log("data_2",data_2)
    });
  });




}

该函数主要两个作用:
一是修改config.js文件,把里面的timestamp值换成最新的时间戳值
二是修改index.html文件,把config.js?version=123456789的后缀123456789换成时间戳,避免浏览器缓存

image.png

第三步 vue实例绑定弹窗

这步不是必须的,因为要在axios的配置文件拦截响应,如果报版本号过期,要弹窗提示用户是否更新页面.
博主用的UI组件是antdvue 1.X,如果想在JS文件用vue的弹窗插件,需要先把这个弹窗插件绑定在vue实例上.

所以在app.vue执行如下操作,给vue实例加个弹窗绑定.
弹窗记得要JS防抖.

mounted(){
   // console.log('app vue')
   // console.log(this.$confirm)
    Vue.$confirm = this.$confirm
  }

第四步 校验版本号

和后端约定,如果版本号旧了,在返回的data对象里code属性报402.
在axios的配置文件,相应拦截回调函数里配置402错误对应的执行代码.
记得按照你和后端的约定修改代码

  response => {
    if (
      response.data.code != 200 &&
      response.request.responseType != "arraybuffer" &&
      response.data.info !== "成功"
    ) {

  

      //版本旧了
      if (response.data.code == 402) {
        console.log('行为分析 接口报402 错误码')

        
      //    location.reload(true) 

          if (timer_request) {
            clearTimeout(timer_request)
          }
          timer_request = setTimeout(() => {
            console.log(88945)
            // localStorage.timestamp = ''
            // location.reload(true) 


            Vue.$confirm({
              title: '检测到新版本,是否立即更新页面?',
              content: h =>(
              <div style="">
                点击取消,后续将不再检测版本,
                除非手动更新页面或者等待浏览器自动更新缓存后才继续检测
              </div>
              ) ,
              onOk() {
                console.log('OK');
                 localStorage.timestamp = ''
                 location.reload(true)
              },
              onCancel() {
                console.log('Cancel');
                localStorage.timestamp = ''
              },
            });




          }, 4000)
        
        
       
        
      }

      return response;
    }

    return response;
  },
image.png

第五步 打包上线

1.如果你是自动部署,比如把代码提交到git,jekines自动部署,代码直接提上去就行
2.如果你是本机打包好后,手动把打包文件传到服务器部署.
那么每次执行打包操作,你的index.html和config.js都会被修改,生成打包文件后记得还原下

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容