本文由云 + 社区发表
在前端, 我们经常会通过 Windows.onerror 事件来捕获未处理的异常. 假设捕获了一个异常, 上报的堆栈是这个:
- TypeError: Cannot read property 'module' of undefined
- at Object.exec (https://my.cdn.com/dest/app.efe91e855d7432e402545e7d6c25d2d9.js:16:29828)
- at htmlLIElement.<anonymous> (https://my.cdn.com/dest/app.efe91e855d7432e402545e7d6c25d2d9.js:25:6409)
- at HTMLDivElement.dispatch (https://my.cdn.com/dest/vendor.eb28ded1876760b8e90973c9f4813a2c.js:1:248887)
- at HTMLDivElement.y.handle (https://my.cdn.com/dest/vendor.eb28ded1876760b8e90973c9f4813a2c.js:1:245631)
这个堆栈, 你看得出问题来吗? 我们发布到 CDN 的脚本文件, 普遍是经过 UglifyJS 压缩的, 所以堆栈可读性相当的差. 假如有下面的一个堆栈查看工具, 又如何?
堆栈查看工具
眼尖的同学, 一眼就能找到问题. 这里的 p[e] 出现了可能为 undefined 的情况.
这样一个工具, 大大提高了问题定位的效率.
好, 这里不卖瓜, 我们来看下这当中的实现原理.
堆栈工具实现原理
一步步来说的话:
拿到原始堆栈字符串, 使用
error-stack-parser
解析为堆栈帧, 每个堆栈帧包含三个最重要的字段:
url - 源码的 URL 地址
line - 堆栈位置行号
col - 堆栈位置列号
对于 url, 我们可以用于加载源码内容, 得到 source
source 使用 UglifyJs https://github.com/mishoo/UglifyJS2 反向美化成多行的代码 prettysource, 并且同时生成 sourcemap
堆栈帧中的 line 和 col 通过 sourcemap 反查, 得到美化后对应的 prettyline 和 prettycol
将 prettysource,prettyline,prettycol 给到 Monaco Editor https://microsoft.github.io/monaco-editor/ 渲染, 就可以得到上述截图的效果
说那么多, 不如贴代码是吧:
- var result = UglifyJS.minify(source, {
- output: {
- beautify: true
- },
- sourceMap: {
- filename: 'pretty.js',
- url: 'pretty.js.map'
- }
- });
- var code = result.code;
- var rawSourceMap = JSON.parse(result.map);
- var consumerPromise = new sourceMap.SourceMapConsumer(rawSourceMap);
- resolve(
- consumerPromise.then(function(consumer) {
- return {
- code: code,
- sourceMapConsumer: consumer
- }
- })
- );
上面就是使用 UglifyJs 对压缩代码进行反向美化的核心代码. 下面给出 SourceMap 的使用源码:
- var code = result.code;
- var consumer = result.sourceMapConsumer;
- var position = consumer.generatedPositionFor({
- source: '0',
- line: lineNumber,
- column: columnNumber
- });
- parent.postMessage({
- event: 'js-prettify-callback',
- payload: {
- hash: payload.hash,
- result: 'success',
- prettySource: code,
- prettyLineNumber: position.line,
- prettyColumnNumber: position.column + 1
- }
- }, sourceOrigin);
完整源码有兴趣的读者也可以下下来把玩把玩:
JS-loader.HTML.zip
源码只包含堆栈解析的实现, UI 的实现不在本文的讨论之内, 用 React 随便画一画就好了.
此文已由作者授权腾讯云 + 社区在各渠道发布
获取更多新鲜技术干货, 可以关注我们腾讯云技术社区 - 云加社区官方号及知乎机构号
来源: https://www.cnblogs.com/qcloud1001/p/10271119.html