还是和平时一样,做完需求,测试通过,愉快地上线。运营侧在大推,推了好几天。突然有一天,都来反馈说页面自己弹出dialog而且关不掉:
这就奇怪了,都跑了几天的项目没问题,怎么突然翻车了?
背景:一个专门做活动的git项目,仅在微信和手Q环境运行。用的是preact,项目结构是该有的都有,pages下每一个文件夹都是一个页面,也能支持第2级文件夹一个页面。每一个活动页面就是一个文件夹,互不影响,mpa。我们的ci系统很慢,部署大项目需要几分钟,然后加上各种环节最快要半小时走完流程,接下来很快将会用另一个方案替代。我活动已经上线几天,是一个运营活动,推广那些学习课程的。同事他们另一个活动后来上线,是一个年度总结活动。突发现网问题,时间非常非常紧张而且是2018最后一工作日前一天晚上,而且我们两个活动必须在元旦前发出去(运营压时间的活动准时上线的重要性大家应该都懂)
项目文件夹
pages
-- act1文件夹
---- conponents
---- index.jsx
---- index.html
-- act2文件夹
---- act4文件夹(都同上)
---- act5文件夹
-- act3文件夹
复制代码
最后act1.html,act4.html,act5.html,act3.html都是不同页面
都上线几天,突然出事,可以肯定的是,不是业务的bug。剩下的原因:现网资源被更改、npm包被更新。跑了一下主分支master代码,没问题。npm run dist模拟生产环境也没问题。
经过询问,原来同事刚刚发布,发完还没合并主分支。一看他的分支,果然是更新了。查了一下ci系统,也找到了记录。于是,切换他的分支跑起来项目代码,然后打断点,弹出方法的函数根本都没有进去,而且控制弹框弹出的state都不是true。
这种情况,首先让我怀疑人生一阵,代码明明没问题而且state也没有让他弹出来。于是再对比现网的和我之前发布的正常版本,来到同一个页面,发现新代码的主逻辑js多了10行代码!!一瞬间我马上想到的是babel插件的问题。因为我正在用同事写的一个Babel插件,功能就是在react的jsx中写类似像vue那种命令。
现网弹框无解弹出关不掉 =》 所对应的state并没有为true =》 代码多了10行 =》 babel插件有问题
问了一下,原来他为了fix那个插件在preact中的一些坑和更新了preact-compact。为什么呢?因为他们的活动需要引入antd不然时间上有风险,引入antd在目前preact的版本并不能跑起来需要升级。升级完成后,antd大部分组件可以正常使用,但select组件是undefined无法使用,效果就是一个叫undefined的什么都没有的标签渲染在页面上,所以他在能跑大部分antd组件的基础上,再手写一个很完美的select。
但是,就是因为升级,导致这个插件有bug。时间紧急,也没有时间去管。定位到问题,马上叫测试回滚,现网我的活动正常运行。接下来的计划是,我把所有的用了指令的地方改回常规方法,然后跟着他们一起发出去。对于版本,测试稳定后,把package.json的^号去掉,把版本稳定下来。刚刚好,他们那边被leader们盯得紧,一些体验问题也要改,所以我也可以坐个顺风车。我改完了,自测没问题,先撤了。他们改完了也自测通过,已是差不多10点,部署上了预发布。
晚上的时候,看见企业微信上的他们顺利上预发布的消息,我也放心了,心里想着第二天过去验证一波就上线。
必须要用antd =》不能用只能升级基础库 =》 导致babel插件问题出现(作者也投入需求没时间理)=》 我的活动和年度总结活动一起放同一个分支上线
当我在公司,代理配置上了预发布,发现资源404和502,一些主js丢失页面崩溃。而且有的手机有缓存复现不了,连电脑修改ua跑微信环境也发现大部分图片资源失败。一开始想到的就是我们的ci系统有点坑,重新部署一次就可以。浪费半小时,结果还是一样。这时候,去检查资源,经过老司机们的同心协力,确定了原因以及解决方案:
我们的部署是增量部署,也就是类似于电脑复制粘贴,有冲突的覆盖无冲突的不变。我前几天上线,今天也改了新代码但是一些静态资源和一些页面完全没有变化,cdn映射也不变,资源名字还是资源+原哈希。问题的根源:这周周一的时候,机器上的文件被清了一次,现在才知情。于是手动把资源拷贝到服务器上,顺利跑起来预发布环境。此时,炸出了这边资源匹配规则不合理的问题,应该改进一下。
预发布资源404和502 =》 机器被清理过 =》 手动补回资源
预发布如期而至跑起来,预发布验证流程愉快走起,没问题后全量发布现网,发布留守时,拉了一堆人体验都没有问题。忽然,一个产品反映,有一个课程不能购买,提示:“请先测试”。测试?什么鬼?测试的东西跑到现网去了?但是又不是必现的问题,某些课程存在这个问题。于是抓包拿到错误码,后台说不知道这是什么原因,我也突然很绝望,leader看见我这样,说:“来,跟我走,我们一起去找他们,不要在这里发企业微信,这样你要搞到什么时候。” 我们找到后台leader,说这个是很久很久之前的逻辑,需要考试才能买这种课(才知道原来课程还有普通的和难的,难的需要考试!这里的“请先测试”文案太抽象,实在容易让人疑惑,我们开发和测试一看上去就觉得是我们业务流程中的功能测试)。但是,运营说发布的时候特地验证过,她可以买。综合两点,只有一个可能,运营很久之前就考过试了。
后来和产品对,最后结论是,产品测试开发都没有知道这个事情,很久之前的逻辑,而且刚刚好运营自己考过试,一直以来都觉得这一切理所当然。此时,前后端产品测试都在,都带着各自的leader,反推一系列的问题找出原因达成一致。方案: 下架尖子课程、修改文案、增加跳转、强行让购买,考虑到时间紧急,而且运营侧必须推尖子课程,最后采取了修改文案的方法,让用户下载app去考试,功能等下期需求完善。不得不佩服老员工解决问题能力和团队沟通能力,如果我自己估计搞到晚上了。
购买难的那种课程弹出“请先测试” =》 这种课程需要考试 =》 除了运营大家都不知道这种逻辑而且运营自测没问题 =》 确认运营曾经考过试,现在能买课 =》 造成一切理所当然的假象 =》 修改文案、下期完善
我这边验证没问题,因为之前遭遇过测试低端机比较晚,发布前很赶而且风险大。刚刚好,他们就遇到了,而且是,部门大老板用安卓机体验到一些不好的地方,他们那边继续修改。除了一些体验问题,然后最后定位到一个fastick的库的问题,是为了解决点透问题的,只是兼容性上出了一些问题。后来有一个操作,有一个同事发现来到一个页面的弹框怎么都关不掉。问题来了,几个同事跑的是不同结果。这很明显是node_modules的问题,根本上还是package.json的版本。经过对比,我们package.json就取掉了^符号而已。
此时,我们的package.json经过几个过程:我发布时是旧的react和preact =》 他们有一个环节需要antd升级了compact并删除了lock.json =》 我的活动发现babel插件问题,修改代码自测通过,一个正则把 package.json的所有^ 去掉保证版本稳定 =》 他们几个人不同的node_modules
为什么还有版本坑?于是我们开始了rm -rf掉node_modules重新安装,后来大家都是一样的效果了。在我们寻找解决方案的时候,突然才想到,去掉package.json的所有^ 并不能解决问题,这不能阻止依赖中的依赖的版本,说锁版本最靠谱的还是lock.json。又一番修改,确定最终package-lock.json,终于上线了!
package.json多次被修改 =》 自测稳定并锁住最终版本
事情并没有结束,有一个同事把工具库里面的一个函数名字写错,现网再出bug,很快解决。后来工具库的作者说这个是废弃的方法,于是又一波讨论下次版本怎么废弃没用的函数。
这次事情引起了很多leader重视,大家都反思并总结,针对问题提出解决方案。
为什么用preact?因为小,而且我也喜欢上一些宽松语法:style可以写字符串、不用在map元素中写key属性、无需担心对被卸载的组件setstate的坑(另一篇文章有讲到这个问题)。但是用了preact意味着不能用react新特性,反正目前是这样,以后应该可以支持。活动页面性能要求高,而且兼容性要做到极致,但preact在我们项目暂时跑不了antd。用不用antd不是问题,但是用不了antd就是一个问题,早晚会踩坑的。
对于我们这个项目,结构就是多页面,每一个页面独立。但是每一次发布也意味着所有的活动页面也会被重新发一次。如果修改基础库,所有的活动都被影响。我们的方案是:删掉之前的页面,发布的时候利用增量发布的特性直接发某个需求,但是旧页面需要找到旧分支才能修改,有点麻烦;或者是稳定版本库,长期不用动它;或者是先用着,等到要改的时候顺便改,旧页面先在分支中删掉。路过的大虾们,对于后续维护上如果有更好的方法可以提一下。
“我只是想安安静静写代码”,这是多美好的期望啊,可是事实上并不能,你要照顾整个团队。大家都是一个team,无论遇到什么都要一起面对,大家都要聚在一起,谁慢了谁快了都要照顾一下。导师也多次和我说:永远别以为你自己跑起来项目就完事了。这次说背锅,貌似谁也没有特别明显的背锅嫌疑。说大家都没错,也是有道理,谁都是做好了自己本分而且正常上线,面对任何难题都解决。说大家都错了,也是说得通,大家都是只看自己的一亩三分地,没照顾整个团队,没照顾整个项目。
最后一个工作日,虽然跌跌撞撞,但是获得了成长,给2018职业生涯画上句号