souce-map-js + Vue 还原生成环境报错,让JS报错无所遁形

1,820 阅读4分钟

前言

最近再写前端监控的系统,写了大概两个月,系统总体能跌跌撞撞跑起来,监控系统通过 sdk获取到http请求 page性能 js报错 上报到服务器。但是js报错让我非常揪心,因为不知道怎么把上报的错误给还原了。

直到我发现了 source-map-js 这个神奇的包!

image.png

这张图是我通过sdk抓取到的js报错,并通过source-map-js error-stack-parser还原出的

准备工作

  1. 先创建一个空的vue项目,然后删掉一些没用的东西。
  2. App.vue 中写入这段代码
export default {
  name: "App",
  data() {
    return {
      testNumber: 1,
    }
  },
  created() {
    this.testNumber = null;
    if (this.testNumber.length > 1) {
      console.log("报错了!");
    }
  }
}

启动项目之后控制台可以看到js的报错,点击下报错的地方我们也能看到具体是哪个位置出错了。

image.png

image.png

那么打包上线了是否也能看到报错的位置呢?

tips: 这里我用的phpstudy 搭建的内网环境

image.png

卧槽翻车了?为啥上线了也能看到?

并没有,部署的时候我把source-map也给放到服务器环境了。

source-map 干啥的呢? 一句话:映射源码

大家在部署项目的时候应该很少会部署source-map把?虽然能还原报错位置,但放上去了项目体积直线上升!

而且 source-map 也不应该被放到服务器上,这玩意扔上去了你的代码简直就是在裸奔,没人愿意自己的代码被"别有用心"的人看到把?

那么在生产的时候我是怎么还原的js报错呢?

一起还原js错误吧!

  1. 先在main.js中配置下vue的错误捕获。
Vue.config.errorHandler = (err, vm, info) => {
  console.log(err,"err");
  console.log(vm, "vm");
  console.log(info, "info");
}

image.png

js报错不在是红色的了~

  1. 引入 error-stack-parser 还原js执行堆栈
import ErrorStackParser  from "error-stack-parser"

Vue.config.errorHandler = (err, vm, info) => {
  const parseError = ErrorStackParser.parse(err);
  console.log(parseError,"err");
  console.log(vm, "vm");
  console.log(info, "info");
}

image.png

  1. source-map 登场还原真·js报错位置

这里一定一定要开启source-map,把项目部署到服务器环境!

这里一定一定要开启source-map,把项目部署到服务器环境!

这里一定一定要开启source-map,把项目部署到服务器环境!

需要先安装axios包,用来获取到咱们的source-map文件


import ErrorStackParser  from "error-stack-parser"
import sourceMap  from "source-map-js"
import axios from "axios"

const LoadSourceMap = (url) => axios.get(url)

Vue.config.errorHandler = async (err, vm, info) => {
  const stackFrame = ErrorStackParser.parse(err);
  console.log(stackFrame, "错误堆栈");
  findCodeBySourceMap(stackFrame[0])
  console.log(vm);
  console.log(info);
}

// stackFrame.fileName 就是报错的Js代码,需要根据这个Js 获取到对应的source-map
const findCodeBySourceMap = async (stackFrame) => {
  const sourceData = await LoadSourceMap(stackFrame.fileName + ".map")
  const fileContent = sourceData.data;
 
  const consumer = await new sourceMap.SourceMapConsumer(fileContent)
  // 通过报错位置查找到对应的源文件名称以及报错行数
  const lookUpResult = consumer.originalPositionFor({
    line: stackFrame.lineNumber,
    column: stackFrame.columnNumber
  })
  // 那么就可以通过 sourceContentFor 这个方法找到报错的源代码
  const code = consumer.sourceContentFor(lookUpResult.source)

  console.log(code, "还原之后的 code")
  // return {
  //   code,
  //   line: lookUpResult.line,   // 具体的报错行数
  //   column: lookUpResult.column,  // 具体的报错列数
  //   name: lookUpResult.name
  // }
}
…

image.png

功能与作用

  1. ErrorStackParser 解析报错信息

    ErrorStackParser 解析出来的出来的是一个数组,这个数组每一个元素都可以解析出来,这里我为了演示就不去一一解析了,感兴趣的小伙伴可以自己去尝试下。

  2. axios 获取到srouce-map文件

    axios 就是用来获取到咱们的source-map文件的,我不建议你直接将source-map放到服务器,因为"别有用心"的人可以下载你的source-map还原你的代码……

    这里我是为了 演示 所以放到服务器上,你可以通过input上传获取source-map 内容(下一篇实现)

  3. source-map-js 还原源代码

    srouce-map-js 就是用来还原源代码的。只要你有source-map文件都能还原!非常强大!

总结

下一篇文章会带大家用 Koa 实现数据上报,并在前端页面展示出具体的报错位置。

再讲讲如何自建前端监控系统以及这俩月的心路历程……

参考

排名不分先后

  1. srouce-map-js
  2. 线上bug追踪之Sentry初步尝试(一)
  3. 利用SourceMap还原前端代码 这篇文章总感觉是从哪里爬来的,没有找到具体的作者。
  4. noerror README.md 有两篇文章建议大家可以去看看!