我正在参与掘金创作者训练营第5期, 点击了解活动详情
前言
一般的bug发布到测试环境就能够及时发现及时修复掉,但是某些兼容性bug则比较狡猾,往往在用户使用的过程中才能被发现,遇到这种情况,我们在线上还原这个bug就已经有很大的难度了,更不用说是及时修复bug,这需要我们不断地在实践中积累经验,以便应付下一次的线上bug;今天我们就来分享一下最近遇到的一个线上问题;
PS:如果不想看问题思考过程可以直接滚动到底部看看经验总结;
场景还原
我们以CSDN为例还原一下场景(并不是csdn有bug,只是借用csdn描述一下当时的bug),如图1
图1:csdn分享弹窗
我们打开手机访问csdn然后点击分享按钮,理想状态下是能够弹出这个分享弹窗的;但是我们用苹果手机微信中打开页面做同样的操作却不显示任何内容,就好像点击事件没有执行一样;安卓手机好的很;我的心理翻江倒海,为啥会有iOS系统这个诡异的系统,...此处省略一万字
但是想归想,出现了问题总是要解决,不可能跟产品说这个功能iOS不支持了,好了硬着头皮来分析一下可能的情况:
- 这个按钮的点击事件没有触发成功
- 触发了点击事件,但是由于某种原因弹窗没有展示出来
但是移动端没有控制台我们没有办法去看是否有log、是否有报错,怎么办呢?
移动端控制台
这里就需要使用到移动端控制台,主要是vconsole,可以在main.js中引入vconsole:
import VConsole from 'vconsole'
if(process.env.NODE_ENV === 'development'){
new VConsole()
}
如果和我一样是SSR项目则需要在mounted生命周期中引入:
async mounted(){
if(process.env.NODE_ENV === 'development'){
const res = await import('vconsole')
new res.default
}
}
注意vconsole的Network中只能看到ajax请求、资源请求,看不到fetch请求,如果要捕捉fetch请求则需要在源码中添加对fetch的捕捉,社区里面有代码实践可以自行查阅
问题解析
到我们的项目中去引入vconsole发现并没有报错而且弹窗状态那段代码已经执行了
那么就考虑是第二种情况,弹窗没有展示,但是在Chrome浏览器的手机模拟器中弹窗是出现了的,那么这会是什么原因呢?遇到这种情况首先想到的就是兼容性问题,那肯定是CSS的兼容性出了问题,我们就从头看一遍弹窗的样式,如图2
图2:样式截图
发现有一个属性比较陌生inset:0,我们查阅一下MDN看一看这个属性的含义
The inset CSS property is a shorthand that corresponds to the top, right, bottom, and/or left properties. It has the same multi-value syntax of the margin shorthand.
翻译过来就是说:inset是定位值的缩写,那么inset:0就等同于top:0;right:0;bottom:0;left:0;,赶紧去caniuse查看一下属性兼容性:如图3
图3:inset属性兼容性
那么微信内置的浏览器内核是什么?QQ浏览器X5内核,看一下上面的兼容性发现QQ浏览器是完全不支持该属性的,所以就造成了样式错乱
别以为问题就这样就解决了,我们发现代码里面根本没有写inset:0这个代码,而我也根本不熟悉它怎么用,那么这个代码是怎么生成的呢?最可能的就是生产环境CSS压缩的时候把定位值简化为inset:0,那么我们去webpack配置里面去查找:webpack中使用到了OptimizeCSSAssetsPlugin、MiniCssExtractPlugin、ESBuildMinifyPlugin,依次注释插件进行打包发现是ESBuildMinifyPlugin开启css压缩之后出现的问题,那么我们可以把它的css压缩关闭掉
关闭之后问题解决
总结
总结一下,我们解决移动端的bug一般分以下几步:
- 在Chrome手机模拟器上运行看看有没有bug
- 切换环境(本地环境=> 测试环境=> 预发环境=> 生产环境)查看是否是环境、编译的原因
- 借助移动端控制台分析问题
- 安卓、iOS系统兼容性问题