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:57515line: 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直接关联起来, 导航到具体的报错文件, 更加直观。