脚本错误量极致优化-让脚本错误一目了然
共 469字,需浏览 1分钟
·
2020-09-07 11:49
授权转载自:joeyguo
https://github.com/joeyguo/blog/issues/14
在上篇
《脚本错误量极致优化-监控上报与Script error》 : https://github.com/joeyguo/blog/issues/13
中,主要提到了js脚本错误上报的方式,并讲解了如何使用 crossorigin 来解决 Script error 报错信息的方案,于是我们就可以查看到脚本报错信息了。而此时可能会遇到另一个问题:”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 文件,处理后得到源文件的具体错误信息。
SourceMap 文件中的 sourcesContent 字段对应源代码内容,不希望将 SourceMap 文件发布到外网上,而是将其存储到脚本错误处理平台上,只用在处理脚本错误中。
通过 SourceMap 文件可以得到源文件的具体错误信息,结合 sourcesContent 上源文件的内容进行可视化展示,让报错信息一目了然!
基于 SourceMap 快速定位脚本报错方案
整套方案的代码实现可以在这 noerror 查看,效果如下
1.左边的为线上页面,上报脚本错误 2.右边的为 noerror 脚本错误监控系统
此时,错误信息中行列数为 1 和 515。结合 sourcemap,经处理(source-map)后,拿到对应的源文件上的具体错误信息,并进行展示。
方案五:开源方案 sentry
sentry 是一个实时的错误日志追踪和聚合平台,包含了上面 sourcemap 方案,并支持更多功能,如:错误调用栈,log 信息,issue管理,多项目,多用户,提供多种语言客户端等,具体介绍可以查看 getsentry/sentry,sentry.io,这里暂不展开。
小总
以上的方案都有各自使用场景,能够解决问题的方案都是好方案。可以先快速支持,然后逐渐过渡到完整的方案。除了这里提到的方案外,社区还有不少其他的优秀方案。
关于 sourceMap 文件的生成,通过 gulp,webpack 都可以很好支持, noerror 的示例使用的是 webpack,只需要设置 devtool: "source-map",具体示例可以查看这里 。
https://github.com/joeyguo/noerror/tree/master/example
然而当项目外链第三方资源或公共库时,这种压缩且无提供 SourceMap 的文件出现异常,又该如何更好的定位错误位置呢?
定位到项目外链第三方资源或公共库
”获取对应格式化后的代码行列位置“
我们可以将压缩代码进行格式化,当错误出现时,错误信息也就有了具体的行列数,更够方便定位到错误位置。
!function(n) {
// ...
// ...
}([ function(n, r) {
function t() {
noerror;
}
t();
} ]);
而此时,格式化后的代码由于增加了换行和空格,增加了文件的大小,所以并不推荐这种方式。但这种试图 “通过压缩代码的出错行列位置转换成格式化代码对应的出错行列位置” 的思路我们可以接着进行优化。将格式化代码的转换进行后置处理。借助工具,避免提前格式化导致的文件增大问题。
“通过压缩代码及行列位置获取对应格式化后的代码行列位置” 的工具
我们可以将压缩代码进行格式化,并结合原来的压缩代码匹配生成“映射文件” - SourceMap 文件。有了 SourceMap 文件后,就能够通过压缩代码的行列数找到对应格式化后代码的行列数了。
小结
当遇到压缩且无源码 SourceMap 的文件出错时,借助上面提到的“工具”,能够找到其对应格式化后的代码及出错位置,更好的定位具体问题。具体工具的使用与实现方式可见 https://github.com/joeyguo/js-beautify-sourcemap
以上为本文所有内容,相关文章:
脚本错误量极致优化-监控上报与Script error: https://github.com/joeyguo/blog/issues/13
脚本错误量极致优化-让脚本错误一目了然: https://github.com/joeyguo/blog/issues/14