前端兼容之痛
作为一名光荣而高大上的前端开发工程师,最痛苦的事情是什么?多年的搬砖经验告诉我,那一定是:
做兼容
故事的猪脚就是首图中这破烂货。要怎么形容他呢?
吃苦耐劳!
都摔成这样了,还坚持服役,内心绝望的同时,还必须流露出一丝钦佩之意
操作系统android 5
这台设备由我们老板亲自小心翼翼的交到我们测试大当家手中,千叮万嘱一定要照顾好他,我们又怎敢怠慢 ~
当我得知,必须兼容这样一台设备时,我的内心毫无波澜!嗯,是的~
这起重大事故发生在我自信满满提交测试之后的2分钟。
刚出炉的安装包,新鲜又甜美,万万没想到在测试手中安装,启动,数据加载...,随后崩的一声,app闪退。
每当遇到这种问题,我就知道事情不简单。
假装淡定的从测试手中拿过手机,通过自己的电脑上安装了调试包,想看看问题出来哪里,如果运气不错的话,报错信息会直接告诉我是哪里有问题。只需要不到2分钟,就能解决问题。
然而 ~
即使是debug模式,也没有任何报错信息,直接就闪退了
没有任何报错信息!!!!
无奈之下,不得不请出Android开发神器,android Studio。使用debug 模式构建,安装,不出所料的继续闪退,好在在Debug窗口中,终于看到了两条弥足珍贵的报错信息。
E/chromium: ### WebView Version 43.0.2357.121 (code 52357121) A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0xc2b4c2b4432861 in tid 26756 (FrescoDecodeExe)
最为一个深耕前端,对android半吊子了解的资深搬砖工而言,看到这个第一反应就是“这是什么鬼东西?”
如果经验缺乏,面对这种完全处于知识盲区的bug时,一定就绝望万分,心生退意了。但是既然已经自诩资深搬砖了,绝望这种情绪又怎可出现?不然岂不是很打脸!
所以,传给各位道友一个八字真言 ~
谷歌在手,天下我有
无脑复制报错信息到谷歌搜索。然后 ~
发现第一条信息和我们的报错信息长得差不多,就是我想要的,内心有点小窃喜,仿佛胜利就在眼前
然而点进去一点,我就蒙蔽了
高赞回答,更令人难过 ~
即使看不懂英文,也能明显感觉到他们讨论的问题已经在我的知识盲区深处,和React Native完全不搭边,虽然我们遇到了类似的报错,可 ~ 这也差太多了
接连点了几条搜索结果,发现内容都不是我想要的,肯定是自己的搜索姿势有问题。于是换一种说法,看看有没有新的结果
搜索 android: Fatal signal 11 (SIGSEGV), code 1
发现有大量的类似问题,并且还出现了几条中文结果。这简直就是意外之喜。
然而 ~
不对!不对!全都不对!
花费了大量的时间,一个挨着一个查看,英文的中文的,姿势换了108种,可都没有我想要的!
内心绝望的我,找到了React Native的issues里。怀揣着微弱的希望,点了进来
这位gay友的描述居然跟我的情况类似,当有大量的组件渲染时,会出现这种崩溃。
看到了一点小希望 ~
看了一眼自己的请求结果,虽然在崩溃,但是请求成功了,并且有122条数据从一个接口过来。
难道真的是因为数据量太大了,android 5 枯老的身躯无法承受导致的崩溃?
既然有了猜想,当然要尝试一下。人为减少接口中数据数量,看看结果会肿么样。
奇幻之旅并未就此结束,验证结果是,及时接口中只有10条数据,闪退问题依然存在,好吧,这位gay友提了一个存在严重错误引导性的问题,怪不得最终那么多人回复也没得到解决方案,闪退问题一定另有他因 ~
阅读到这里,可能只需要不到5分钟,可我看了看时间,我已经折腾到了晚上八点。所以别问我加班那么忙在干什么了
我在玩Google!!!
可惨痛的经历一次又一次的告诉我
谷歌不是万能的!!!
到了这个时候,我已经明确的知道,谷歌已经帮不了我了。那么,我应该绝望吗?我应该!但是我没有
那应该怎么办?
打断点吗?当然不是,作为一个特别的工程师,用这种大众化的调试方式岂不是很没面子?( ﹁ ﹁ ) ~
我用的方法是:删除可能存在问题的代码,在尝试过程中一步一步缩小问题代码可能出现的范围,并最终定位到问题所在
经过之前的一堆瞎折腾,虽然没有最终找到问题所在,但也不是全无所获。
app表象上虽然是启动时闪退,但是并非真的启动闪退,而是启动之后执行了某些操作闪退
数据量大的那个接口出现问题的可能性最大
有了这个思路,方案基本确定。先干掉这个接口的相关操作,然后看看会是什么情况
于是,我注释掉了一段关键代码
然后摇一摇手机,重新reload代码。奇迹出现了,App重新运行后神奇的不再闪退了。ლ(^ω^ლ)
你能想象这个时候我的心情吗 ~
仍然毫无波澜!
虽然方向对了,这个神秘的bug就要漏出它最隐秘的本体。但是作为一个成熟的搬砖者,知道过早的得意忘形太容易被打脸了,所以我必须沉得住气,距离成功越近,就越不能着急
一步一步继续缩小范围,看看是否是数据问题,还是组件渲染问题。
继续重新运行程序,数据加载进来了,App没有闪退。
既然数据正常,那么问题就一定出在我们自己封装的组件Session
里了。进入该组件,继续观察,寻找可能出现问题的点
机智的我一眼就看出来组件内部有一个map循环。问题大概率出现在这里。
根据多年的经验,map过程中,如果数据类型处理不当,出问题的概率大,因此先用最简单的方式看看数据渲染出来会是什么样子。于是用下面的代码替换了原本的SingleEntry组件。
<Label>{`${item.text} - ${item.key} =${icons[item.key]}`}</Label>
当我看到运行结果,这个bug就已经完全失去了神秘色彩,问题逐渐暴露出来,因为,渲染出来的数据结果中,居然有undefined
进入到SingleEntry组件中才发现,该组件完全没有对从外界接收的三个参数做任何异常处理。
最终知道真相的我简直想要暴走,
这T!M!是!谁!写!的!垃!圾!代!码!
怎么可以犯这么低级的错误...(。•ˇ‸ˇ•。) ...
在决定启用最终方案的10分钟后,找到了问题的原因。
React Native的Image组件,在android 5中,往属性source中传入undefined,会导致app崩溃!
问题解决了,然而内心并没有很喜悦,花了一个下午加一个晚上的时间,解决了这么个破问题,我内心的苦涩,估计没人能懂 ~
我几乎倾尽毕生所学,本以为将要被我征服的,是那种解决了就能吹嘘两个月的超级bug
谁知道 ~
所以,这个时候就体现出了好好利用Typescript的重要性。如果严格按照约定,凡是不符合规范的数据就不能传入到数据中,那么这个问题在开发阶段就能够被避免。
最后总结几点
•遇到未知bug不要恐惧•多多利用google搜索•解决问题不要拘泥于形式•对数据做异常判断非常重要
前端做兼容,真的苦