项目没发版却出现了bug,原来是chrome春节前下毒

16,006 阅读4分钟

前言

  • 农历: 腊月二十五
  • 阳历: 2023-01-16

过年和年兽

已经临近过年,公司的迭代版本也已经封版,大家都在一片祥和又掺杂焦虑的气氛中等待春节的到来。 当然,等待的人群里面也有我,吼吼哈嘿。

突然企业微信的一声响,我习惯性的抬头瞅了一眼屏幕,嗯? 来至线上bug群?

不过因为最近咱前端项目也没有发版,心里多少有点底气的。

于是怀着好奇的心情点开了群消息, 准备看看是什么情况。

结果进群看到是某前端页面元素拖拽功能的位置失效了。晴天霹雳啊,我们有一个类似给运营做自定义活动页面,说是无法拖拽了。然后需要做活动比较紧急,需要尽快修复。

这活脱脱就是跟着春节来的年兽啊。我还没放烟花打年兽,年兽就先朝我冲过来了,那说什么也得较量较量了。

项目背景

我们这个功能是属于一个基础功能,通过npm私有仓库维护版本

这个基础功能呢,很多项目中都在使用。

如果基础功能发了新版本,业务部门不进行升级安装,那么这个业务线的项目也是不会出问题的。所以只要线上出了问题,那么要满足两个条件

1、基础功能进行了发布了npm新版本,且这个版本有问题

2、业务部门进行了升级,使用了这个新版本

排查问题

一般来说:造成问题的可能性有

  1. 有人发过新迭代版本
  2. 是不是存在莫名的缓存
  3. 有人在以前的版本里面下毒了,然后现在发作了(可能性不大)

经过粗略排查

猜测结果
1、发版导致?近期两周,该服务部分未更新,排除
2、缓存导致已经清理,没用,排除
3、下毒了看了相关代码,没什么问题,排除

问题初见端倪

接着发生了两件事情

1、然后我本地跑了一下项目的时候,在操作的时候,存在报错。

2、一个测试兄弟反馈说他那儿可以正常操作

这他么莫不是浏览器兼容问题了吧。

我去他那看了一下,都是chrome浏览器(这个项目我们只支持到chrome就可以)

这时的我感觉可能问题有点大了,莫不是chrome又调整了吧

点开测试兄弟的版本看了下,是108,而且处于重启就会升级的状态。 我赶紧回到我的工位,打开电脑发现是109。

image.png

在看了下那个报错, event.path为undefined, 这里先介绍下path是个什么玩意,他是一个数组,里面记录着从当前节点冒泡到顶层window的所有node节点。我们借助这个功能做了一写事情。。。

这直接被chrome釜底抽薪了。(path属于非标准api, 这些非标准api慎用,说不定什么时候就嘎了)

解决问题

1、问题一

既然是event.path没了,那么我们怎么办呢,首先得找到代替path的方法, 上面我们也说了,path里面记录的是从当前节点冒泡到顶层window的所有node节点(我们是拖拽事件)

image.png

那么我们可以自己遍历一下当前节点+他的父节点+父节点的父节点+...+window

    let path = [];
    let target = event.target;
    while(target.parentNode !== null){
      path.push(target);
      target = target.parentNode;
    }
    path.push(document, window);
    return path;

在项目里面试了一下,emm,很稳定。

1、问题二

但是我们又遇到了第二个问题,使用到event.path的项目还比较多,这就日了狗了 如果没有更好的方法,那么我只能挨个项目改,然后测试,然后逐个项目发版

这种原始的方法我们肯定是不会采用的,换个思路,既然event下的path被删除了,那么我们在event对象下追加个一个path属性就可以了

当然我们要记得判断下path属性是否存在,因为有部分用户的chrome是老版本的,我们只对升级后的版本做一些兼容就可以了

if (!Event.prototype.hasOwnProperty("path")){
    Object.defineProperties(Event.prototype, {
      path: {
          get: function(){
              var target = this.target;
              console.log('target', target)
              var path = [];
              while(target.parentNode !== null){
                  path.push(target);
                  target = target.parentNode;
              }
              path.push(document, window);
              return path;
          }
      },
      composedPath: {
          value: function(){
              return this.path;
          },
          writable: true
      }
    });
}

这样,我们只需要在每个项目的根html,通过script引入这个js文件就可以了

反思

如题,这个事情怪chrome吗?其实不能怪的。 1、chrome在之前就已经给出了更新通知,只是我们没有去关注这个事情 2、本身event.path不是标准属性,我们却使用了(其实其他浏览器是没有这个属性的,只是chrome提供了path属性, 虽然现在他删除了) 3、总之还是自己不够警惕,同时使用了不标准的属性,以此为戒,共勉