webpack插件开发之异常日志收集插件

最近要做一个前端异常日志收集的功能,仔细想想,如果只是做一个日志上报的功能,貌似没多大意义。本着服务大众的想法,结合之前图片重试功能的开发,何不开发一个webpack插件来完成收集日志的功能呢。最终目标就是只需要简单配置一些配置项,就可以自动生成一份异常监控的代码,insert到入口文件。

先看看使用效果:

配置以下打包脚本:

   plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
            filename: './index.html',
            minify: true,
            inject: false,
            showErrors: true,
            chunks: ['vendors', 'index']
        }),
        new ExceptionReportPlugin({
            srcPath: '../demo/src/index.html',  // 必须, 入口文件
            ratio: 'commonConfig.ratio', // 上报比例 必填 默认 0.1
            loggerSwitcher: 'commonConfig.logger', // 监控开关 必填
            jsSwitcher: 'commonConfig.jsswitcher', // jserro开关 必填
            exceptionWhiteList: 'commonConfig.exception_whitelist',
            business: 'yourdomain Or keyword', //必传,业务标记
            headerScript: 'exceptionReport', // 头部的script标记 不可修改
            footerScript: 'bottomScript' //  底部的script标记  不可修改
        })
    ],

打包后的效果

在此之前,我发现目前错误监控的方式比较粗暴,在入口文件的底部有一段用于捕获异常的脚本:

window.onerror = function(message, source, lineno, colno, error){
     doReport(message, source, lineno, colno,error)
     // doReport 为上报异常的方法
}

后来发现,这样捕获到的异常非常少的,查阅了一些资料,发现代码还是存在以下问题。

首先,使用window.onerror捕获异常存在一些局限性。

了解下window.onerror:当JavaScript运行时错误(包括语法错误)发生时,window会触发一个ErrorEvent接口的事件,并执行window.onerror();但语法错误会导致出现语法错误的那个脚本块执行失败,所以语法错误会导致当前代码块运行终止,从而导致整个程序运行中断,如果语法错误发生在我们的错误监控语句块中,那么我们就什么也监控不到了。

window.onerror 捕获不到资源加载异常的情况,此时考虑使用事件监听window.addEventListerner(‘error’)来捕获异常。也就是说window.onerror 与 window.addEventListener(‘error’)相比较,后者能捕获的异常更加全面一些。

另外window.onerror,无法捕获Promise异常。最新的规范中定义了 unhandledrejection事件用于全局捕获promise对象没有rejection处理器时异常情况。

前端框架是怎么捕获错误?

有同事发现在vue框架中某些错误并没有被捕获,后来发现VUE提供了专门的方法Vue.config.errorHandler来处理捕获到的错误。

// err: 捕获到的错误对象。
// vm: 出错的VueComponent.
// info: Vue 特定的错误信息,比如错误所在的生命周期钩子
Vue.config.errorHandler = function (err, vm, info) {}

此外还存在一个问题,如果入口文件head部分有js脚本,底部的onerror 可能捕获不到异常。

基于上面的分析,我们需要重新编写代码来捕获异常。

我个人的思路是:

  1. 在页面head部分插入内联的js脚本,用于收集异常,异常收集要涵盖上述几个方面;
  2. 在页面底部加入内联的js脚本,对收集到的异常集中上报处理。
  3. 通过打包工具,将脚本植入到指定的文件相应的位置中。

所以,工作包含两个方面:

  1. 实现异常捕获和异常日志上报脚本
  2. 实现打包插入脚本的插件

先说webpack插件开发:

因为项目中用到了html-webpack-plugin插件,作用就是生成html入口文件,具体如何使用这里就不展开。

html-webpack-plugin 插件作者提供了插件事件,允许其他插件来改变html文件内容。提供事件如下:

Async(异步事件):

* html-webpack-plugin-before-html-generation // 生产html之前
* html-webpack-plugin-before-html-processing // 处理html文件之前
* html-webpack-plugin-alter-asset-tags // 处理tag 比如link srcipt 之后
* html-webpack-plugin-after-html-processing // 处理html文件之后
* html-webpack-plugin-after-emit
Sync(同步事件):

* html-webpack-plugin-alter-chunks

我们可以使用这些事件来开发自己的插件。

function newPlugin(options) {
  // 配置项处理
}

newPlugin.prototype.apply = function(compiler) {
  compiler.plugin('compilation', function(compilation) {
    compilation.plugin('html-webpack-plugin-before-html-processing', function(htmlPluginData, callback) {
      // todo 对htmlPluginData.html进行处理,然后返回
      // to do 骚操作,将打包好的脚本 insert到入口文件中
      callback(null, htmlPluginData);
    });
  });

};

module.exports = MyPlugin;

接下来就是如何组织异常捕获和异常上报的通用代码了:

参考:

https://segmentfault.com/a/1190000016959011

https://www.cnblogs.com/datiangou/p/10224846.html

 

发表评论

记录工作生活点滴。

返回
顶部