摘要: 堆棧是Debug的關鍵。html
Fundebug經受權轉載,版權歸原做者全部。前端
在前端,咱們常常會經過 window.onerror
事件來捕獲未處理的異常。假設捕獲了一個異常,上報的堆棧是這個:git
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 壓縮的,因此堆棧可讀性至關的差。假若有下面的一個堆棧查看工具,又如何?github
眼尖的同窗,一眼就能找到問題。這裏的 p[e]
出現了可能爲 undefined
的狀況。app
這樣一個工具,大大提升了問題定位的效率。工具
好,這裏不賣瓜,咱們來看下這當中的實現原理。post
一步步來講的話:url
拿到原始堆棧字符串,使用 spa
error-stack-parserdebug
解析爲堆棧幀,每一個堆棧幀包含三個最重要的字段:
url
- 源碼的 URL 地址line
- 堆棧位置行號col
- 堆棧位置列號url
,咱們能夠用於加載源碼內容,獲得 source
prettysource
,而且同時生成 sourcemap
line
和 col
經過 sourcemap
反查,獲得美化後對應的 prettyline
和 prettycol
prettysource
、prettyline
、prettycol
給到 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 隨便畫一畫就行了。