JS 代碼壓縮後,定位具體出錯代碼困難!。本篇《腳本錯誤量極緻優化-讓腳本錯誤一目了然》 将結合示例,通過多種解決方案逐一分析,讓腳本錯誤 一目了然。
示例 · 壓縮代碼定位錯誤困難1.源代碼(存在錯誤)
`function test() {
noerror // <- 報錯
}
test();`
2.經 webpack 打包壓縮後産生如下代碼
`!function(n){function r(e){if(t[e])return t[e].exports;var o=t[e]={i:e,l:!1,exports:{}};return n[e].call(o.exports,o,o.exports,r),o.l=!0,o.exports}var t={};r.m=n,r.c=t,r.i=function(n){return n},r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{configurable:!1,enumerable:!0,get:e})},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,r){return Object.prototype.hasOwnProperty.call(n,r)},r.p="",r(r.s=0)}([function(n,r){function t(){noerror}t()}]);`
3.代碼如期報錯,并上報相關信息
`{ msg: 'Uncaught ReferenceError: noerror is not defined',
url: 'http://127.0.0.1:8077/main.min.js',
row: '1',
col: '515' }`
此時,錯誤信息中行列數為 1 和 515。結合壓縮後的代碼,肉眼觀察很難定位出具體問題。
如何定位到具體錯誤方案一:不壓縮 js 代碼這種方式簡單粗暴,但存在明顯問題:1. 源代碼洩漏,2. 文件的大小大大增加。
方案二:将壓縮代碼中分号變成換行uglifyjs 有一個叫 semicolons 配置參數,設置為 false 時,會将壓縮代碼中的分号替換為換行符,提高代碼可讀性, 如
`!function(n){function r(e){if(t[e])return t[e].exports
var o=t[e]={i:e,l:!1,exports:{}}
return n[e].call(o.exports,o,o.exports,r),o.l=!0,o.exports}var t={}
r.m=n,r.c=t,r.i=function(n){return n},r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{configurable:!1,enumerable:!0,get:e})},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n}
return r.d(t,"a",t),t},r.o=function(n,r){return Object.prototype.hasOwnProperty.call(n,r)},r.p="",r(r.s=0)}([function(n,r){function t(){noerror}t()}])`
此時,錯誤信息中行列數為 5 和 137,查找起來比普通壓縮方便不少。但仍會出現一行中有很多代碼,不容易定位的問題。
方案三:js 代碼半壓縮 · 保留空格和換行uglifyjs 的另一配置參數 beautify 設置為 true 時,最終代碼将呈現壓縮後進行格式化的效果(保留空格和換行),如
`!function(n) {
// ...
// ...
}([ function(n, r) {
function t() {
noerror;
}
t();
} ]);`
此時,錯誤信息中行列數為 32 和 9,能夠快速定位到具體位置,進而對應到源代碼。但由于增加了換行和空格,所以文件大小有所增加。
方案四:SourceMap 快速定位SourceMap 是一個信息文件,存儲着源文件的信息及源文件與處理後文件的映射關系。
在定位壓縮代碼的報錯時,可以通過錯誤信息的行列數與對應的 SourceMap 文件,處理後得到源文件的具體錯誤信息。
image
SourceMap 文件中的 sourcesContent 字段對應源代碼内容,不希望将 SourceMap 文件發布到外網上,而是将其存儲到腳本錯誤處理平台上,隻用在處理腳本錯誤中。
通過 SourceMap 文件可以得到源文件的具體錯誤信息,結合 sourcesContent 上源文件的内容進行可視化展示,讓報錯信息一目了然!
基于 SourceMap 快速定位腳本報錯方案
整套方案的代碼實現可以在這 noerror 查看,效果如下
1.左邊的為線上頁面,上報腳本錯誤 2.右邊的為 noerror 腳本錯誤監控系統
此時,錯誤信息中行列數為 1 和 515。結合 sourcemap,經處理(source-map)後,拿到對應的源文件上的具體錯誤信息,并進行展示。
方案五:開源方案 sentrysentry 是一個實時的錯誤日志追蹤和聚合平台,包含了上面 sourcemap 方案,并支持更多功能,如:錯誤調用棧,log 信息,issue管理,多項目,多用戶,提供多種語言客戶端等,具體介紹可以查看 getsentry/sentry,sentry.io,這裡暫不展開。
小總
以上的方案都有各自使用場景,能夠解決問題的方案都是好方案。可以先快速支持,然後逐漸過渡到完整的方案。除了這裡提到的方案外,社區還有不少其他的優秀方案。
關于 sourceMap 文件的生成,通過 gulp,webpack 都可以很好支持, noerror 的示例使用的是 webpack,隻需要設置 devtool: "source-map"
然而當項目外鍊第三方資源或公共庫時,這種壓縮且無提供 SourceMap 的文件出現異常,又該如何更好的定位錯誤位置呢?
定位到項目外鍊第三方資源或公共庫”獲取對應格式化後的代碼行列位置“我們可以将壓縮代碼進行格式化,當錯誤出現時,錯誤信息也就有了具體的行列數,更夠方便定位到錯誤位置。
`!function(n) {
// ...
// ...
}([ function(n, r) {
function t() {
noerror;
}
t();
} ]);`
而此時,格式化後的代碼由于增加了換行和空格,增加了文件的大小,所以并不推薦這種方式。但這種試圖 “通過壓縮代碼的出錯行列位置轉換成格式化代碼對應的出錯行列位置” 的思路我們可以接着進行優化。将格式化代碼的轉換進行後置處理。借助工具,避免提前格式化導緻的文件增大問題。
“通過壓縮代碼及行列位置獲取對應格式化後的代碼行列位置” 的工具
我們可以将壓縮代碼進行格式化,并結合原來的壓縮代碼匹配生成“映射文件” - SourceMap 文件。有了 SourceMap 文件後,就能夠通過壓縮代碼的行列數找到對應格式化後代碼的行列數了。
小結
當遇到壓縮且無源碼 SourceMap 的文件出錯時,借助上面提到的“工具”,能夠找到其對應格式化後的代碼及出錯位置,更好的定位具體問題。具體工具的使用與實現方式可見
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!