前端JS错误捕获--sourceMap

前言

在我们的项目开发中,随着项目的不断完善,线上bug的捕获、调试和处理是越来越重要,那如何来解决这个问题呢?

传统方案

1、增加多个console.log来打印报错信息
2、弹alert提示用户
或者是升级一步,捕获用户的报错,上传错误日志
通常情况下在try-catch里捕获错误信息,或者window.onerror里捕获。

可以了解window.onerror捕获异常的同学,可以学习一下
前端window.onerror异常监控
用window.onerror捕获并上报Js错误的方法

但是这样做: 产生的问题,由于现在工程化的项目,一般都要对项目的js、css、html等资源进行压缩,比如说使用webpack来进行打包,这个时候,我们之间报错的信息是压缩前代码的,而这些报错信息对于我们来说,几乎没用,我们无法通过报错信息找到对应的原始文件。

那我们如何来解决呢?

sourceMap

对于这个我就不详细介绍了:(不太清楚的同学可以看看下面的文章)
javaScript Source Map 详解
debug 工具 —— source-map

对于使用webpack打包的同学来说,我们只需要将发布环境的打包命令做一下修改即可:

sourceMap: 'source-map',  // 这里可以根据实际需求来设置

这样一来我们打包后就会生成我们的业务文件和.map文件

如果我们将这里生成的.map文件一同发布到服务端,打开网页后,打开开发者工具,切换到sourse
前端JS错误捕获--sourceMap_第1张图片
如图:2所示的地方,就是我们打包后的文件根据sourceMap解析后的文件,与我们本地项目开发的文件目录时一一对应的,这样如果线上报错,我们也能够通过这个进行调试.

测试对比:

我们直接在文件里加入一个报错:

throw new Error("报错啦!");

没有加sourcemap的报错:

前端JS错误捕获--sourceMap_第2张图片
这个时候我们点击报错信息,跳转到main.js中,是一堆压缩的代码,我们直观上是看起来比较头疼的。

加上sourceMap后的报错信息:

前端JS错误捕获--sourceMap_第3张图片
这个时候,我们点击进入,发现,进入的文件跟我们本地是对应的,这里我们能够快速的定位bug的产生位置,非常的方便高效。

这样做不是说就万无一失了,存在安全的问题,具体解决方案可以参考如下地址:
你所不知道的sourceMap

这样就完了么?
并没有,我们这样只能够事实的进行错误分析,如果是用户使用过程中产生的 我们必须要有一个监控机制才行。

监控中使用sourceMap

前面提到的window.onerror来监控页面报错:
这里我们需要将报错日志上传到日志系统中,这里我们选择上传当前报错的全部信息:
这里借鉴网友的处理error方式:
前端window.onerror异常监控

window.onerror = function(msg, url, row, column, error) {
      setTimeout(function(){
        let errormsg = "";
        //不一定所有浏览器都支持col参数
        column = column || (window.event && window.event.errorCharacter) || 0;
        if (!!error && !!error.stack){
            //如果浏览器有堆栈信息直接使用
            errormsg = error.stack.toString();
        }else if (!!arguments.callee){
            //尝试通过callee拿堆栈信息
            let ext = [],f = arguments.callee.caller, c = 3;
            //这里只拿三层堆栈信息
            while (f && (--c>0)) {
               ext.push(f.toString());
               if (f  === f.caller) {
                    break;//如果有环
               }
               f = f.caller;
            }
            errormsg = ext.join(",");
        }
        // 日志收集函数
        sendMonitorErrorInfo(msg, url, row, column, errormsg)
      },0);     
    }

说明一下:
这里的 error.stack中包含当前错误栈中的报错信息,便于我们后面来追踪bug;

分析报错日志

前端JS错误捕获--sourceMap_第4张图片
可以看到这里的报错信息是我们打包后的文件中的,这是非常不方便寻找错误的,这个时候,我们之前打包的.map文件就可以非常好的帮我们找到错误的源代码位置了。

有兴趣的同学可以参考一下这篇文章:
细说 js 压缩、sourcemap、通过 sourcemap 查找原始报错信息

这里我们需要使用一个库: sourcemap
source-map

const fs = require('fs');
const SourceMap = require('source-map');

const { readFileSync } = fs;
const { SourceMapConsumer } = SourceMap;

// 这里是我们的.map文件地址
const rawSourceMap = JSON.parse(readFileSync('path/to/js/map/file', 'utf8'));

SourceMapConsumer.with(rawSourceMap, null, consumer => {
  const pos = consumer.originalPositionFor({
    line: 1,   // 报错的行
    column: 982  // 报错的列
  });

  console.log(pos);
});

例如我刚才截图的那个报错信息:
找到第一行的:
http://localhost/43y/js/main.99aae90e.chunk.js:2:331638
这里我们需要去使用:main.99aae90e.chunk.js.map文件,来查找第2行,第331638列
这里找到报错信息:
前端JS错误捕获--sourceMap_第5张图片
通过这种方式,我们将报错信息查找回来了,对应到了我们项目中的位置。

注意:
我这里仅仅是做了一个简单例子,有兴趣的同学,可以把这个source-map集成到日志分析系统里面,将日志直接分析成对应的原文件。

你可能感兴趣的:(前端开发)