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

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

作者: 折叠幸福 | 来源:发表于2023-11-15 17:55 被阅读0次

    一:需求
    页面打包上传到服务器后,用户能在自己电脑上立即感知到更新
    二:需求分析
    调研后得知:
    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都会被修改,生成打包文件后记得还原下

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/hpnswdtx.html