发布以后,线上报错了,咋办?有没有很恐慌?
每次上线都战战兢兢得生怕出错,又得搞到凌晨一两点,烦死了?这是不是你的现状?作为一名资深程序员,我深知大家得不容易,所以今天奉上一本解决现场问题得法宝。具体如下:
(方法千变万化,没有最好,只有更好,如果大家有更好得办法可以在评论区共同探讨,共同成长,谢谢!)
上线以后,为什么会出现问题?
问题来源有2种:
1.现场数据更加复杂,在uat测试阶段,由于数据相对比较简单,测试人员得临界值设定得并不准确,导致bug没有找出来。
2.前端代码有问题,在测试的时候没有测试出来,发布以后发现了。
解决办法:
第一: 假设这就是后端数据问题,我们需要用一个chrome 插件: Ajax-intercetion
下载:直接执行
git clone https://github.com/YGYOOO/ajax-interceptor.git
下载下来以后,直接拉进chrome的插件里面就好了,当然你也可以从chrome 的插件商店里面直接下载,我的window10的chrome的插件商店被拦截了,进不去,只能从仓库里面获取。不管从哪里获取,拿到就好,无需较真。最后你可以得到如图所示的标志:
1.把需要拦截的接口地址输入ajax-interceptor的 url 的设置里面,然后刷新页面,触发相关功能。
2.在chrome的devtool里面的network里面找到相关接口的数据,直接ctrl+A复制response
3.把上面复制好的响应数据放到 ajax-interceptor 的 replace Response with 里面,然后把你觉得异常数据找到,改成合理的数据,然后触发相关功能,你修改后的数据就会展示到页面上。此时就能断定是不是数据问题了。
如果你不会用,没有关系,我为大家找了一个说明视频,大家可以点进去看看:
4.经过我们一系列的骚操作,终于发现不是数据问题呀,有没有想死的心都有了?
第二:现在断定一定是代码的bug, 可是线上错误指向的是一个压缩文件呀,咋办?
想解决个bug,咋就这么难呢?心里喷涌而出的草泥马,算了,不抱怨了,为了早点下班,还是老老实实想一下解决办法,才是正事,你说对不对!我也不兜圈子了看下面。
线上无法调试的根本原因就是没有 suorcemap 呗,说白了就是打包的时候我们配的是 hidden-source-map,而不是source-map,他们的区别是啥?
首先 hidden-source-map 和 source-map 在打包的时候都会产生一个 .map 文件,而且他们处理后的文件大体是一样的,唯一的区别就是source-map处理后的文件下面多了一行代码,如图所示:
我做了个测试代码,一个用source-map打包,一个用hidden-source-map打包,具体可以看:juejin.cn/post/738022... 结果如下
用http-server将他们同时启动
进入页面看看
明显他们的目录访问目录不一样,是不是?解决问题的根本就是把index.js和index.js.map用 //# sourceMappingURL=index.js.map关联在一起,他们就能找到源码了,我们就可以欢乐的调试它了,对不对?
方法1.利用chrome的 add sourcemap 功能,如下:
设置add sourcemap的文件的时候,你可以连本地的,反正是对应的.map文件就好了,如果没有出来,一定是你的地址不对,赶紧改路径吧。
此时8081的页面和8082的页面就一摸一样了,你是不是就可以开心的调试了呢,一眼看过去就能知道,线上到底是哪一行在报错。
方法2.手动映射
1.在项目里面安装source-map库
npm i source-map -D
2.在项目里面建立一个source.js文件
只需要修改红框的地方即可,操作如下:
js
const { SourceMapConsumer } = require('source-map')
const fs = require('fs')
const rawSourceMap = fs.readFileSync('./dist/index.js.map', 'utf-8')
// 填入错误信息
originalPositionFor('index.js:1:161')
function originalPositionFor(errInfo) {
const [budleName, line, column] = errInfo.split(':')
SourceMapConsumer.with(rawSourceMap, null, (consumer) => {
const originalPosition = consumer.originalPositionFor({
line: parseInt(line),
column: parseInt(column),
})
console.log('bundle name = ', budleName)
console.log('original position = ', originalPosition)
})
}
是不是很美丽呀!
方法3. 用Charles代理
其实代理的目的就是对源文件进行拦截,然后在response的文件里面加上//# sourceMappingURL=index.js.map,此时的url你可以写线上的map文件,也可以指定本地文件对应的.map文件,也就是说,
可以这样://# sourceMappingURL=index.js.map
- 也可以这样://# sourceMappingURL=http://127.0.0.1/index.js.map
具体如下:
设置断点地址
2.如果此时Charles没有工作,很可能是因为你chrome的代理插件没有关闭,关闭就可以正常工作了。
其实精髓就是要index.js和index.js.map连接起来,当然对面的大神们,你们肯定有更好的解决方法,不防在评论区说下,我来给大家补充全面,必经程序的发展本就靠的是大家的集思广益,不是单打独斗!
谢谢!