如何优雅地查看 JS 错误堆栈?

本文由云+社区发表html

在前端,咱们常常会经过 window.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 压缩的,因此堆栈可读性至关的差。假若有下面的一个堆栈查看工具,又如何?git

img
堆栈查看工具

眼尖的同窗,一眼就能找到问题。这里的 p[e] 出现了可能为 undefined 的状况。github

这样一个工具,大大提升了问题定位的效率。app

好,这里不卖瓜,咱们来看下这当中的实现原理。工具

img
堆栈工具实现原理

一步步来讲的话:post

  • 拿到原始堆栈字符串,使用ui

    error-stack-parserurl

    解析为堆栈帧,每一个堆栈帧包含三个最重要的字段:spa

    • url - 源码的 URL 地址
    • line - 堆栈位置行号
    • col - 堆栈位置列号
  • 对于 url,咱们能够用于加载源码内容,获得 source

  • source 使用 UglifyJs 反向美化成多行的代码 prettysource,而且同时生成 sourcemap

  • 堆栈帧中的 linecol 经过 sourcemap 反查,获得美化后对应的 prettylineprettycol

  • prettysourceprettylineprettycol 给到 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 随便画一画就行了。

此文已由做者受权腾讯云+社区在各渠道发布

获取更多新鲜技术干货,能够关注咱们腾讯云技术社区-云加社区官方号及知乎机构号

相关文章
相关标签/搜索