记录一次诡异的线上问题,顺便领点意外的零花钱

127 阅读4分钟

技术栈背景: { ..., "ant-design-vue": "~3.2.15", "vue": "^3.2.45",... }

事情是这样的: 前两天春节假期结束刚上班,运营反馈线上使用的CMS平台弹窗没办法关闭,找到组内的前端小伙伴问什么情况。 我正好也在旁边就过去一起看看,结果发现一个因为版本号引起的问题。 因为公司的CI/CD机器我们没办法登录进去,只能通过CI机器的日志来查看问题,但是发现没啥用,没啥有用的日志输出。也猜测过是安装包的版本问题,前期也检查过,本地一切正常,测试环境一切也正常,但是线上环境就异常

前端小伙伴首先在本地打开页面,经过反复测试弹窗功能正常,后面发到测试环境发现还是一切正常,又改了弹窗文件js,重新发了生产环境 确认了打包的静态资源的contentHash也变了,但是功能还是不正常(更改文件是为了确保hash变更,不是缓存造成的干扰)。

线上环境代码是经过压缩混淆的,下面的代码截图只是方便大家解读和理解

结论: vue3.4.x 源码变更了组件update方法。

  • v3.4.0-alpha.1 版本以上 和v3.4.0-alpha.1 以下的版本在这里的差异主要是组件的渲染,增加了 effect.dirty 这个判断

  • 这个 effect 在vue3里面相当于vue2的 Watcher实例,我们先来复习下 vue2有三种 Watcher实例(render watcher 我们俗称的渲染watcher,computed watcher, watcher api的 watcher) Vue2 每个组件都是一个 Watcher实例,所以每个组件都有update方法。computed 对象的每个 value 也是一个Watcher实例。我们直接使用的 watch 对象的每个 value 也是一个Watcher实例。

  • vue3 没有使用 Watcher, 使用了Effect,本质上和 vue2 的Watcher一样,都是充当观察者角色。收集页面上使用被变更的数据

  • 3.4.x 版本以下 @vue/runtime-core的 render.ts 更新组件的写法

image.png

  • 3.4.x 版本以上 @vue/runtime-core的 render.ts 更新组件的写法

image.png

下面是探究的过程,觉得啰嗦可跳过:
  • 在弹窗产生的地方打断点,发现弹窗对象上有两个方法update和destroy,分别对应的是ant-design-vue更新弹窗和销毁弹窗方法

01e2b9cc-0413-4c84-aac7-7995e2ec71a1.jpeg

  • 在断点处,手动调用 window.testaa.destroy(window.testaa 是我手动在 window上面挂的弹窗实例) (), 弹窗依然没有关闭。通过定位到ant-design-vue的源码,发现在组件更新这里出现了问题(confirmDialogInstance.component.update())

image.png

image.png

至此, 断点过程已经结束,我们也顺利找到了问题,vue3.4.x 源码变更了组件update方法。刚开始,我们的同学以为是代码问题,花了点时间去查找,遇到问题还是要静下心来仔细查找

疑问点:
  • 3.4.0版本距今发布已经2个月了,为什么现在才出现这个问题? 我仔细查过也想过这个问题
  • 我们一直使用的是pnpm来安装包,pnpm有缓存node_modules安装包的能力, 我们业务写的vue版本是^3.2.45,这里的^ 代表大版本不升级即可,所以3.4.x 是符合我们这里^符号的规则,也合理的解释了为什么出现了 3.4.x版本的依赖。
  • 为什么测试环境 本地环境都是正常的,线上不正常?
  • pnpm在安装过程中优先查找缓存的npm包,本地因为缓存过3.2.x版本的包,所以删除node_modules 再次安装此时拉取的还是缓存里面的包,所以功能也还是正常展示的。
  • 线上不正常的原因我想了很久没有想通,我一开始猜测,有一个A项目依赖了 vue 3.4.x 这个版本,他在CI机器第一次构建的时间点比我们第一次构建的时间点要早(我们这个是最近迁移到这个CI机器的,之前这个CI机器有其他项目在跑),我们项目正好用了^3.2.45, 此时 A项目的 vue 3.4.x也符合我们的安装语义,但是在随后的测试中这个观点不成立,希望知道原因的读者在评论区留下答案
规避点:
  • 拿到一个新项目先看下依赖,心中做到一个大概的预知,发现问题,往几个可能存在的方向去验证,大胆猜测,小心验证
  • 版本控制要做好(建议不要直接写死版本,这样没办法拥抱别人更新的新特性)
  • github上关于这个问题的两个 issues
  • github.com/vueComponen…
  • github.com/vuejs/core/…
意外的零花钱:
  • 访问这个url: provisions.starknet.io/
  • 点击这里,输入自己的github名字即可看到有多少个币(一个接近2美元,汇率目前7.2 --> 2 * 7.2 * 你的币)

image.png

  • 比如: yyx990803(vue作者) 中了价值 1500¥ (不要的话欢迎打给我,我的钱包地址: 0x124109a84D8378b75ddc30Cf6f5e177dCB3B1c86)

image.png