如何優雅地查看 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 隨便畫一畫就行了。

此文已由做者受權騰訊雲+社區在各渠道發佈

獲取更多新鮮技術乾貨,能夠關注咱們騰訊雲技術社區-雲加社區官方號及知乎機構號

相關文章
相關標籤/搜索