线上出bug了?别怕,这么定位!
摘要: Source Map还是很神奇的。
- 原文:线上出bug了?别怕,这么定位!
- 公众号:前端小苑
Fundebug经授权转载并修改,版权归原作者所有。
工作中,生产环境代码是编译后代码,搜集到报错信息的行和列无法在源码中对应,很多时候只能靠“经验”去猜,本文针对这种情况,开发了一个npm命令行小工具,帮助快速定位报错的源码位置,提升效率。
由于现在构建工具盛行,前端部署的代码都是经过编译,压缩后的,于是乎,SoueceMap就扮演了一个十分重要的角色,用来作为源代码和编译代码之间的映射,方便定位问题。
测试SourceMap功能
首先全局安装reverse-sourcemap
npm install --global reverse-sourcemap
选择编译后的代码进行测试,下面是vue项目编译生成的代码。

在命令行执行命令,将main.js反编译回源码,并输出到sourcecode目录下。
reverse-sourcemap -v dist/main.a8ebc11c3f03786d8e3b.js.map -o sourcecode

上面是执行命令输出的sourcecode目录,生成的目录结构和源码目录一致,打开一个文件,和源码做下对比:

可以看出,反编译出的代码无论目录结构还是具体代码都和源码一致。
生产环境代码报错如何定位源码位置
如果使用了Fundebug的Source Map功能的话,则可以很方便的定位出错位置:

如果没有使用监控工具的话,生产环境的代码,经过压缩、编译,很不利于Debug。针对这个问题,需要准备一份生产环境代码的map文件,为了方便,可以在项目的package.json增加debug命令用来生成map文件。这条命令除了开启sourcemap,其他的具体webpack配置和生产环境配置相同。
"scripts": {
"start": "vue-cli-service serve --mode dev",
"stage": "vue-cli-service build --mode staging",
"online": "vue-cli-service build",
"debug": "vue-cli-service build --mode debug"
}
有了map文件,通过SourceMap提供的API就可以定位到源码的位置。下面是实现的核心代码。
// Get file content
const sourceMap = require('source-map');
const readFile = function (filePath) {
return new Promise(function (resolve, reject) {
fs.readFile(filePath, {encoding:'utf-8'}, function(error, data) {
if (error) {
console.log(error)
return reject(error);
}
resolve(JSON.parse(data));
});
});
};
// Find the source location
async function searchSource(filePath, line, column) {
const rawSourceMap = await readFile(filePath)
const consumer = await new sourceMap.SourceMapConsumer(rawSourceMap);
const res = consumer.originalPositionFor({
'line' : line,
'column' : column
});
consumer.destroy()
return res
}
最重要的就是使用SourceMap提供的 originalPositionFor API。 SourceMapConsumer.prototype.originalPositionFor(generatedPosition)
originalPositionFor API的参数为一个包含line和column属性的对象
line 编译生成代码的行号,从1开始
column 编译生成代码的列号,从0开始
这个方法会返回一个具有以下属性的对象
{
"source": "webpack:///src/pages/common/403.vue?c891", // 源代码文件的位置,如果无法获取,返回null。
"line": 4, // 源代码的行号,从1开始,如果无法获取,返回null。
"column": 24, // 源代码的列号,从0开始,如果无法获取,返回null。
"name": "get" // 源代码的标识,如果无法获取,返回null。
}
源码定位工具
为了使用方便,我将这个功能做成了一个命令行小工具。全局安装后,不需要做任何配置就可以使用。
安装
npm install --global source-location
参数介绍
Usage: sl [options]
Options:
-v, --version output the version number
-p, --source-flie-path The generated source file 编译后的map文件
-l, --ine The line number in the generated source 编译后代码行号
-c, --column The column number in the generated source 编译后代码列号
-h, --help output usage information
使用案例
终端执行命令:
sl -p dist/1.f47efcb58028826c7c05.js.map -l 1 -c 34
命令行将会输出:源码的文件路径:path,源码行号:line,源码标识:name。

项目的github地址: github.com/front-end-y… 如有错误欢迎指出。
最后,推荐大家使用Fundebug,一款很好用的BUG监控工具,支持Source Map功能~
线上出bug了?别怕,这么定位!的更多相关文章
- 被产品经理怼了,线上出Bug为啥你不知道
前言 前几天跟读者聊天,他说被产品经理给怼了.原因是线上出 Bug 了,最后是客户反馈才知道的. 我就问他:你们是不是没做监控? 读者:我们是刚成立的创业团队,目前最重要的就是堆功能,很多基础设施都没 ...
- 关于线上的bug什么时候修复的思考
这里系统专门指的是那种用户量大的系统,比如有几百万或者上千万的注册会员.因为小系统因为用户量少,不存在这种思考,考虑有时候是多余的.另外还有内部系统,给自己公司内部人员使用的,即便是出现了问题,也不会 ...
- 一个线上程序bug,由通用补数程序引起
下游发现接口可用率非100%,马上线上查看,发现数据在有些情况下通用补数的数据是空, 有20%的用户是没有相应偏好等的数据的,需要通用补数来补数,结果通用补数没有数据. 通用补数数据的检查报警时必须要 ...
- 线上调试bug
在以往的工作中,线上一有bug,就需要把文件弄到本地来改,但经常会碰见本地环境又和线上不一样,导致调试困难,闭着眼睛改好之后传到线上去看对不对,不对的话又要改,循环往复,要多麻烦就有多麻烦啊. 今天给 ...
- 互联网IT当线上出现 bug 时,是怎么处理的?
线上BUG说处理方法:1.关于线上BUG问题,目前公司有一整套线上故障流程规范,包括故障定义.定级.处理流程.故障处理超时升级机制.故障处理小组.故障处罚(与故障存在时长有关)等:2.最主要的是,线上 ...
- 线上应用bug跟踪查找-友盟统计
线上的应用只要用心点点都能发现些bug,连微信,QQ也不列外.但是bug中最严重的算是闪退了,这导致了用户直接不能使用我们的app. 我们公司是特别注重用户反馈和体验的,我们会定期打电话咨询用户的使用 ...
- 不停机不更新代码线上调试BUG的工具
如果你有以下痛点,请你查看本文章: 1.我改的代码为什么没有执行到?难道是我没 commit?分支搞错了? 2.遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗? 3.线上遇到某个用户的 ...
- Android线上Bug热修复分析
针对app线上修复技术,目前有好几种解决方案,开源界往往一个方案会有好几种实现.重复的实现会有造轮子之嫌,但分析解决方案在技术上的探索和衍变,这轮子还是值得去推动的 关于Hot Fix技术 Hot F ...
- 【MySQL 线上 BUG 分析】之 多表同字段异常:Column ‘xxx’ in field list is ambiguous
一.生产出错! 今天早上11点左右,我在工作休息之余,撸了一下猫.突然,工作群响了,老大在里面说:APP出错了! 妈啊,这太吓人了,因为只是说了出错,但是没说错误的信息.所以我赶紧到APP上看看. 这 ...
随机推荐
- 《java数据结构与算法》系列之“开篇”
大学的时候学习数据结构,当时吧虽然没挂这门课,但是确实学的不咋地,再但是其实自己一直都觉得数据结构很重要,是基础,只有基础好了,后面的路才能走的更好. 懒惰真的是天下的罪恶之源.所以一直到现在都毕业了 ...
- C++编译错误fatal error C1004: 发现意外的文件尾
出现这种情况就是类或者结构体的定义后面没有加“;”导致的. 而且这种问题好难排查.
- session 存入redis 或 memcache 的方法
Session简介 session,中文经常翻译为会话,其本来的含义是 指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session.有时候我们 ...
- c#日期计算
/// <summary> /// 计算日期的间隔(静态类) /// </summary> public static class dateTimeDiff { /// < ...
- 微服务常见安全认证方案Session token cookie跨域
HTTP 基本认证 HTTP Basic Authentication(HTTP 基本认证)是 HTTP 1.0 提出的一种认证机制,这个想必大家都很熟悉了,我不再赘述.HTTP 基本认证的过程如下: ...
- mac 上执行 rm -rf /
# 很可怕的指令,清空磁盘所有资料,千万不要用 sudo 尝试,吓的小心肝差掉跳出来 rm -rf / 无聊,想执行rm -rf /会怎样,想起没加sudo时对~/download执行提示权限不足,被 ...
- springboot 大致启动流程
SpringApplication的run方法的实现是我们本次旅程的主要线路,该方法的主要流程大体可以归纳如下: 1) 如果我们使用的是SpringApplication的静态run方法,那么,这个方 ...
- DOM学习之图片库切换效果
addloadevent(prepareplaceholder()) addloadevent(prepareGallery()) //页面加载完时执行函数 function addloadevent ...
- 递归、作用域、生命周期(day09)
数组可以作为形式参数使用 数组做形式参数的时候真正的形式参数并 不是数组而是一个可以作为数组使用的 变量 数组形式参数里包含的存储区都不是被调用 函数提供的 声明数组形式参数的时候可以省略中括号 里的 ...
- Centos 7.x 源码编译搭建Nginx
环境: centos 7 防火墙关闭 Selinx关闭 Nginx Web安装 安装依赖库 yum install pcre-devel pcre gcc gcc-c++ zlib zlib-deve ...