• 前端覆盖式发布引发的使用体验提升


    我们公司前端采用的是覆盖式发布,过程就是:每次上线时构建好前端项目,将构建产物丢给运维,运维直接用新构建直接替换掉线上的版本(一般小作坊应该都是这么搞的...为啥这么搞?我想理由应该是想同的,在此我就不过多解读了)简单粗暴的背后隐患是很大的:假设这么个场景,有用户a和用户b有在使用我们的平台,有一天某时某刻,a正在使用我们的平台,成功登陆后,开始操作balabala,然后a没有关浏览器窗口,也没有关电脑,然后出去嗨了...在a嗨的同时,我们公司可爱的前端同学修复了一个bug,测试好了之后上线了一版,恰巧上线完成之后,b用户也来访问我们的平台,跟a一样的操作,没有出什么问题,但是a这时候继续使用我们平台的时候,问题就来了,发现点击好多页面没有反应,万幸的是a会武术,a打开f12后发现好多js文件404了?什么 ,我嗨之前不是好好的吗?怎么嗨完回来就gg了...

    分析

    仔细详细详细,这种场景下,用户a的问题是不是偶发还是必然?当然是必然了。。。不要给方案上的缺陷找借口了。。。现在前端开发一般是webpack构建项目,在html只会写一个入口的js文件,多个页面的js文件都会被webapck切分代码在配置中映射起来,通过webpack.require来进行懒加载。比方说用户页面和设置页面,用户访问用户页面(没有打开设置页面),这个时候我们修改设置页面并更新一个新版本,用户在打开设置页面的时候就会出现js404:入口js文件记录的设置页面还是修改前的js哈希文件,我们上线后会覆盖掉之前的文件,因此用户就会报js404错误。。。

    解决

    发布方案估计在很长一段时间没得改了。。。那就只能在现有基础上改了。。。在网上查找了解到有人使用 addEventListener 这种方法,第三个参数必须为true,使用捕获传播(因为是监听资源的错误),如下

    window.addEventListener("error",  handler, true)

    思路就是,如果监听到错误,判断是否为js错误,然后获取js的src值,进行一次HEAD请求,确认是否http返回状态码为404,如果是404的话提示用户更新版本(刷新页面)后再使用:

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
    <script>
      /**
       * 判断js资源是否返回404状态码
       * @param url
       * @return {Promise<any>}
       */
      function isScript404(url) {
    
        return new Promise((resolve, reject) => {
          let xhr = new XMLHttpRequest()
          xhr.open('HEAD', url, false)
    
          xhr.onreadystatechange = function () {
            if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 404) {
              resolve(true)
              return
            }
    
            resolve(false)
          }
    
          xhr.send()
        })
      }
    
      /**
       * 处理错误函数
       * @param e
       */
      async function handleError(e) {
        console.log('script resource load error....')
    
        let script = e.target
        let SCRIPT = 'SCRIPT'
        let tagName = script.tagName
        let src = script.src
    
        // js资源网络请求失败
        if (SCRIPT === tagName) {
          let bool = await isScript404(src)
          if (!bool) {
            return
          }
          console.log('更新版本,请刷新页面')
        }
      }
    
      // 绑定事件
      window.addEventListener('error', handleError, true)
    </script>
    <script src="b.js"></script>
    </body>
    </html>
  • 相关阅读:
    mybatis generator插件开发
    webserver实现
    Linux的selinux
    oracle从备份归档日志的方法集中回收
    百度地图 Android SDK
    Oracle实践--PL/SQL表分区的基础
    js插件---jquery给表格添加行列
    m_Orchestrate learning system---三十四、使用重定义了$的插件的时候最容易出现的问题是什么
    2018十大国产佳片
    javascript对象使用总结
  • 原文地址:https://www.cnblogs.com/hanshuai/p/12213356.html
Copyright © 2020-2023  润新知