真实项目中遇到的前端bug以及解决思路

4,703 阅读6分钟

遇到了什么bug

最近在项目中遇到了一个奇怪的问题,一开始还以为很简单,结果却花了不小的精力才算是解决。 该bug表现为偶然会出现左侧菜单栏处于收起状态时,点击菜单,会出现多个tooltip同时显示的问题。 如下图所示: SCR-20230922-shyj.png

复现过程

在经过详细测试之后,可以稳定复现出bug了,这很好,只要是能稳定复现的bug大多数都是可以解决的。 该bug的复现流程为:鼠标在点击菜单之后快速移开,tooltip不会消失,准确的说在页面卡顿时移开鼠标,则tooltip不消失。 bug.gif

解决bug的过程

1.查找资料

这个bug目前是在菜单栏上出现问题,tooltip提示是Menu在收起后自动显示的,所以第一步可以去github上ant-design项目的issues上去找找。 很快找到了一个非常符合这个bug的issues,链接:github.com/ant-design/… 但是在查看源代码后,发现这个bug早在antd 3.19.1就已经解决了,搜索引擎中也没有找到有价值的资料,只能靠自己了。 说到这里,有必要说明一下,项目中使用的技术栈:

"dependencies": {
	"@ant-design/pro-layout": "4.11.4",
  "antd": "~3.26.20",
  "react": "^16.14.0",
  "react-dom": "^16.14.0",
  "umi": "^3.5.38"
}

antd使用的版本大于3.19.1,虽然极为相似,但是应该并非相同的原因导致的。

源码分析

分析源码是必不可少的一步,不管是业务bug,还是组件bug。 查看菜单点击相关源代码,基本逻辑为:

  1. 调用的就是umi的history.push,执行的路由跳转功能,每次点击菜单项,都会跳转到另一个页面,没有找到明显的bug原因。
  2. 根据url,将当前menu设置为selected状态。

整个逻辑较为简单清晰。无法确定bug,需要进一步的分析。

bug的可能性猜想和排查

  1. 根据bug的表现,可以看到存在卡顿的现象,js线程被阻塞,项目复杂,功能多,第三方库性能存在问题,导致鼠标移入移出事件未被触发。

image.png 在使用dev tools查看事件日志之后,发现mouseout事件是有被执行的,这个猜测被排除。

image.png 2. 如果页面不卡顿,其实这个bug是很难被复现出来的,但是项目过于复杂,Menu组件依赖的trigger以及ag-grid性能存在问题,很难对项目进行性能方面的优化,而且也不能治标。 3. react组件发生了重新渲染,导致鼠标移入移除事件不是在同一个组件上发生的。

li.gif 可以看到在点击切换之后,li元素颜色发生了变化,这说明li元素是删除后再新增的,极大可能是这个问题导致的bug。

  1. 怀疑是antd、react、umi依赖的react-router-dom版本导致的问题。

4.排除法

最小demo复现法

结合上面的第2点和第3点,我们可以创建一个新的项目,依赖的umi、react、antd、@ant-design/pro-layout包版本与项目中的保持一致。 Sep-22-2023 22-41-12.gif 为了模拟项目卡顿,还特意在页面中模拟了执行耗时逻辑,发现bug并未被复现,而且li元素也不存在重新渲染的情况,仅更新了class属性。 这说明基本可以排除第三方库版本问题。

替换法

有了上一步不存在bug的代码,那么就可以进行替换排除了,将demo中的菜单相关代码复制替换到项目中,发现bug消失了,但是li还是会被删除再重新渲染。 到这里,以上的猜想几乎都可以被推翻了,问题到底出在哪里呢?

排除法

因为已经没有了思路,结合上面的替换法,其实可以发现bug是可以被修复的,这说明还是项目的代码存在问题,那么最后的办法就是排除法,也就是删除法,一切被我怀疑的代码都将被我删除。 将替换的代码部分全部还原。 经过我一个多小时的各种删除排查后,确定了两个地方会导致出现bug image.png

太奇怪了,为什么呢? 第一个,删除第115行的className后,bug修复 查看gant-menu-item样式定义的css,继续使用排除法,删除我认为可能存在问题的css之后,越发奇怪了,这个bug开始出现了偶然失灵的情况,之前还从来没遇到过这种奇怪的现象。 gant-menu-item内部比较复杂,涉及到许多的自定义样式。 第二个删除Icon组件后bug修复 为什么在删除Icon组件后,bug就没了 这里说明一下,117行的Icon组件并不是antd的Icon,而是项目中基于antd的Icon封装的Icon,在查看了这个封装的Icon之后,发现其内部逻辑较为复杂,可以合理怀疑这个封装的组件导致的这个bug。 随后,我自己基于antd的Icon封装了一个Icon,替换了之前的Icon组件,bug的确消失了。

再次验证** bug的可能性猜想和排查中的第2条**,发生点击菜单时,li元素依然存在删除和新增的情况。

为什么?到底是为什么呢?想不明白?

猜测

大概率还是antd的Menu存在bug 当页面性能存在问题 Menu菜单点击切换后,li真实元素发生删除再新增的较大更新之后 可能是这三个因素堆叠在一起才触发了这个bug。

感想

网上有一些关于前后端对立的文章,前端觉得后端简单,后端觉得前端简单。其实如果是简单的增删改查,其实前后端都差不多,没什么难的。但是大家都各有各的难处。 我在上一家公司做的no-code平台,这个东西其实是对前端要求较高要求的,前端话语权更大。目前在职的公司是业务性公司,业务功能基本在后端,所以后端话语权更大,前端相对来讲没有那么重要。再加上我之前也写过java,不敢说是全栈,也算是前后端都体验过的人了。 还有一些前端已死的说法,其实前端要死的话,那后端其实也差不多,大约80%的简单功能前后端都能被AI取代。大家要死一起死,谁也逃不了的,还是努力提升自己的技能吧。

后续

这个bug花费了约3个工作日,历时约2周时间。虽然bug算是解决了,但是bug产生的机理依然不明白。因为项目时间原因,只能到此为止了。也许在项目后续升级为antd5后,该bug会消失。 这个bug影响其实不大,对业务也不存在影响。但是偶尔出现,会极大影响用户的使用体验。从前端的角度上讲,影响其实是比较大的。 写这篇文章,一是因为这个bug相当的有意思,比较复杂,而且也不算是彻底的解决了,记录之。二是为了记录一下自己在解决bug时的思考过程,希望能帮助到大家。