专栏首页前端之心如何优雅地查看 JS 错误堆栈?
原创

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

在前端,我们经常会通过 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 压缩的,所以堆栈可读性相当的差。假如有下面的一个堆栈查看工具,又如何?

堆栈查看工具

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

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

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

堆栈工具实现原理

一步步来说的话:

  • 拿到原始堆栈字符串,使用 error-stack-parser 解析为堆栈帧,每个堆栈帧包含三个最重要的字段:
    • 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);

完整源码有兴趣的读者也可以下下来把玩把玩:

源码只包含堆栈解析的实现,UI 的实现不在本文的讨论之内,用 React 随便画一画就好了。

喜欢本文的,请不要吝啬点赞转发,特别喜欢的,欢迎给我打赏😍。

同时欢迎在评论区和我讨论。

订阅我们的专栏「前端之心」,每周都会有干货。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 解决 "Script Error" 的另类思路

    前端的同学如果用 window.onerror 事件做过监控,应该知道,跨域的脚本会给出 "Script Error." 提示,拿不到具体的错误信息和堆栈信息。

    小芭乐
  • Markdown 编辑器指南

    Markdown 是一种轻量级标记语言。语法简单明了,浏览本篇指引文章,学会使用markdown,就可以开始写文章了。markdown编辑器采用左边纯markd...

    小芭乐
  • markdown编辑器书写格式说明

    GFM 是 Github 拓展的基于 Markdown 的一种纯文本的书写格式。

    小芭乐
  • Spring Cloud Sleuth服务跟踪

    https://gitee.com/lm970585581/cloud-config/tree/master/Spring%20Cloud%20Sleuth%E...

    HUC思梦
  • 关于MySQL varchar类型最大值,原来一直都理解错了

    关于MySQL varchar字段类型的最大值计算,也许我们一直都理解错误了,本文从问题出发,经实践验证得出一些实用经验,希望对大家的开发工作有些帮助~

    架构精进之路
  • Vue中鼠标事件

    乐心湖
  • 零碎的java知识点记录(一)

    老梁
  • Excel事件(三)工作簿事件

    大家好,上节介绍工作表事件,本节将介绍工作簿事件,工作簿数量较多,但并没有工作表事件常用,只简单介绍几个常用的工作簿事件。

    无言之月
  • day77_淘淘商城项目_10_ Nginx代理详解 + 单点登录系统工程搭建 + 接口文档讲解_匠心笔记

    目前访问后台系统:   http://localhost:8081/ 目前访问首页系统:   http://localhost:8082/ 目前访问搜索结果页面...

    黑泽君
  • Xctf攻防世界-Misc基础题攻略

    攻防世界答题模块是一款提升个人信息安全水平的益智趣味答题,用户可任意选择题目类型进行答题。

    Aran

扫码关注云+社区

领取腾讯云代金券