下午市场部的同事反馈了一个 Bug,说是移动端的页面挂时间长了会出现页面卡死的情况。这个问题之前都没出现过,算是第一次出现这个问题。
首先我开始回想自己写的代码,如果是我代码的问题,只有可能是设备权限轮询导致,但我都禁止在移动端设备上执行相关逻辑了啊。而且起初刚上这个功能的时候也没这个问题,只有可能是其他同事写的代码有问题了。
这样的问题说实话还是比较难定位的,首先我就是借了多台不同 iOS 系统版本的设备复现问题。测试的 16.1 非常容易出现,我的 15.6 时间长了可能会出现操作卡顿(但会缓慢恢复),而 iOS 同事的 16.3 就没出现问题。
我把我的手机接入电脑打开控制台也没发现什么异常。最终只能凭我的经验排查了,一般造成卡顿都是性能方面遇到了问题,我怀疑是大量创建 DOM,内存泄漏,以及未清除的事件监听什么的。(这个问题我也吐槽给 @Innei 了,他自然就是一句话:“重写吧”)
我使用 Chrome 的开发者工具切换到移动端界面,果不其然发现被创建了大量的事件监听,点击内存 Tab 的释放按钮也始终无法释放掉,为什么会创建这么多呢?我直接顺着代码搜索,还好使用 addEventListener
的代码并不多,我很快就发现了问题所在,是一个 useEffects
下的代码下一直在创建事件监听,而且是 document
的点击事件,依赖一变就执行,且没有清理逻辑,这不卡就奇怪了。
这是另外一个同事写的“防止熄屏”代码,用了一个叫“noSleep”的库,原理貌似是模拟播放一段视频。每次执行 Effect 的时候都会创建一个实例,并且绑定一个点击事件,这样才能开始“播放视频”。
我把代码删了之后在本地测试,大量创建监听器的问题果然没了。这波问题我也有责任,毕竟老大让我来做前端小组长,让我去 Code Review,这部分修改我并没有完全看完。接下来想要再次避免这样的问题,我提议让写代码的人多做测试,自己提交前也看看代码,改动后进行全员通知等等。