生產環境通過SourceMap還原壓縮後JavaScript錯誤,快速定位異常

chromedev發表於2019-04-27

(如果你對 source-map有了解,但是不知道具體怎麼實現,操作,可以跳過前面的,直接看底部列列舉的參考文章)

大家都知道一般我們前端的JavaScript程式碼上線前都會壓縮,混淆處理,減小程式碼體積的同時還相對安全些,線上程式碼一般是這樣的

carbon (17).png-182.5kB

舉一個具體例子 原始碼是這樣的

.......
function buyVip(){
    // 判斷是否購買的是已經購買過的自動續費商品
   let { auto_renew } = this.vipData.vip;
   if( !this.isIOS == auto_renew.expire_type){
    console.log("you are ios vip")
   }    
}
.....
   
複製程式碼

壓縮後是這個樣子

this.buyVip(this.selectInfo)},buyVip:function(t){var e=this;localStorage.setItem("vip_buy_goods",(0,l.default)(t)),this.timer=setTimeout(function(){if(!e.loginState)return e.loginActiveRouter="payVipOrder",u.default.openViewByRouter("bridge://user/login"),!1;var i=e.vipData.vip.auto_renew;if(!e.isIOS&&e.isSelect&&i&&1==i.auto_renew&&t.expire_type==i.expire_type&&t.expire_val==i.expire_val){var n=1==i.platform?
複製程式碼

結果由於 auto_renew 是個null,程式碼報錯了,報錯資訊如下

{
 message: "Cannot read property 'auto_renew' of undefined",
 url: "http://xxx.com/vip.024973a2.js",
 row:1,
 col:876
}
複製程式碼

這樣你根據錯誤資訊來定位具體的程式碼很不容易,這個例子還有 auto_renew 這個關鍵字,能根據關鍵字查,有的是 Cannot read property [0] of undefined" 只看錯誤行數,開發小哥哥想哭,肉眼很難定位的具體問題的

哪怎麼樣才能定位到具體錯誤啊?

要不不壓縮程式碼,直接原始碼上,這是不可能的,程式碼體積太大,安全也是個大問題,那我們在本地開發的時候,預設也是打包後的檔案,用Chrome 咋就能看到原始碼,其實就是利用的 SourceMap 技術來除錯,SourceMap簡單的講,就是維護一個原始碼和壓縮後程式碼一一對應的檔案,通過壓縮後的錯誤資訊反向推出原始碼錯誤具體行號,剛才上面那段程式碼,map檔案如下

{
    "version": 3,
    "sources": ["vip.024973a2.js"],
    "names": ["buyVip",],
    "mappings": "AAAA,QAASA,KAEL,GACIC,GAAW,UAAYC,IAC3BC,SAAQC,IAAIH,GAGhBD",
    "file": "hello.min.js",
    "sourceRoot": "",
    "sourcesContent": ["function buyVip()\n{\n  let { auto_renew } = this.vipData.vip\n ...."]
}
複製程式碼

這裡面的主要點是 mapings,是一個很長的字串,它分成三層,記錄了壓縮前後程式碼對行關係,具體map怎麼記錄的可以參考文章末尾的參考文章

那現在前端打包工具(webpack,gulp,rollup)都支援這個SourceMap功能,打包後類似這樣

carbon (1).png-132.2kB

我們需要做的是把 打包後的 SourceMap 檔案儲存起來,然後根據上報的錯誤資訊來反推具體行號了,強調下 SourceMap 檔案是不要跟著打包後的js一起部署的,這樣你線上的程式碼人家是很容易拿到的,相當於裸笨,所以需要在打包指令碼做文章,把 .js 和 .map 檔案獨立出來,看個圖(圖是從網上找到,參見參考文件)

網上圖

這樣在錯誤平臺就能展示錯誤了

企業微信截圖_20190427225913.png-30.9kB
錯誤的展示平臺,我們用的 Node.js 實現的,Firefox 開源一個 source-map 的包,非常好用,具體可以看github, 實際上 source-map 是一套成熟的技術,網上資料很多,可以搜來看看 那這裡僅僅是完成了一個最小的程式碼錯誤復現的閉環, 如何在gitlab ci 裡統一剝離 source-map 檔案和壓縮後 js 檔案,如何對多專案source-map 檔案儲存,如何對單專案多版本制定儲存規則,都是需要考慮的 第一個 統一剝離,因為我們公司的前端部署是統一的部署指令碼的,所以在公共的指令碼里做了處理,這也說明了,前端有統一的部署是多重要,不然單獨專案接,會把人煩死,專案多了,一定要,工程化,流程化,統一化 版本儲存規則,目前是 專案名/gittag/

還有一個問題是 source-map 檔案其實挺大的,而且是不變的,在Node.js 最好用Redis快取,我們初期專案接入不多,我先在記憶體裡做了快取

這個最小的閉環已經能很好的協助解決JavaScript 錯誤問題,但是還不能做到頁面的監控,

  • 頁面錯誤的歸類
  • 比方某天客服反應 ,武漢這個區域,大面積使用者報錯,或者是頁面直接打不開
  • 根據手機平牌,時間點,地域,來篩選錯誤
  • 某個使用者出現錯誤的前10秒,使用者都有哪些操作行為
  • 網路請求大面積報錯
  • CDN載入失敗

這些都是需要解決的問題,出現了問題,怎麼樣預警,通知到開發,是不是能做到智慧的處理,都是後面需要考慮的,所以還有很多工要做,有了新的進展,我會同步記錄下來。

插一句哈,Vue 丟擲的異常是沒有具體行號的,需要經過處理才能上報上去,可以在github搜下 github.com/occ/TraceKit,專門格式化異常的(吐槽下中文搜尋到 處理 source-map 的文章,都是一樣的還互相抄,說到Vue錯誤處理都是直接跳過,要處理Vue異常的一定記得看下這個庫,幫助很大)

這周九天班,趕緊睡覺去了。

參考文章:

相關文章