sourcemap是什么以及怎么生成就不过多阐述了,这是之前看到的一篇文章感觉介绍的很详细:弄懂 SourceMap,前端开发提效 100%
浏览器加载sourcemap
我们线上代码一般不会开启sourcemap,在排查线上的问题时,可以通过浏览器自带的能力加载sourcemap
自建sourcemap服务
在某些情况下我们没办法直接用浏览器加载sourcemap来使用,比如我们的监控平台捕获到了错误栈,但是页面不能复现,只能通过日志的相关信息来排查,此时便需要自建的sourcemap解析服务来处理了。我们可以通过source-map
这个包处理。
/**
* 如其名, 用来消费sourcemap
*/
const {SourceMapConsumer} = require('source-map')
const fs = require('fs');
const path = require('path');
// 错误行
const LINE = 1;
// 错误列
const COLUMN = 205;
// sourcemap文件路径
const ORIGIN_FILE_PATH = path.join(__dirname,'./sourcemap.js.map');
// sourcemap文件内容
const ORIGIN_FILE_CONTENT = fs.readFileSync(ORIGIN_FILE_PATH, 'utf-8');
/**
* 解析Source Map文件
* 通过文件读取的方式, 将sourcemap文件传入
*/
SourceMapConsumer.with(ORIGIN_FILE_CONTENT, null, consumer => {
/**
* originalPositionFor
* 传入编译后文件的位置信息
* 得到对应的源码位置信息
*/
const originalPosition = consumer.originalPositionFor({
source : fs.readFileSync(path.join(__dirname,'./sourcecode.js'), 'utf-8'),
// 举例: 报错堆栈信息为, test.js:40:57515
line: LINE,
column: COLUMN
});
/**
* originalPosition是一个对象, 包含定位到的
* 源代码文件位置
* 和具体定位的行列信息等
*/
console.log('originalPosition:',originalPosition);
/**
* sourceContentFor 通过解析出的路径
* 得到源代码的文本信息
*/
const content = consumer.sourceContentFor(consumer.sources.find(source => source === originalPosition.source));
/**
* content就是对应的源代码的原始文本了
*/
console.log('原始代码:',content);
function getLineByIndex(str, lineIndex) {
const lines = str.split(/\r?\n/); // 使用正则表达式兼容所有平台
if (lineIndex >= 0 && lineIndex < lines.length) {
return lines[lineIndex];
} else {
throw new Error("行索引超出范围");
}
}
const errorLine = getLineByIndex(content, originalPosition.line - 1);
console.log('具体报错行代码:',errorLine);
});
输出效果
根据上述信息, 我们可以扩展出一个功能更完善的工具
比如在团队内部部署一个微型服务, 自助上传souremap, 输入报错信息, 然后打印出具体的错误,还可以做报错代码的高亮展示等优化,更进一步地, 可以跟git直接关联起来, 导航到具体的报错文件, 更加直观。