type
status
date
slug
summary
tags
category
icon
password
前言
项目上线之后,用户如果出现错误(代码报错、资源加载失败以及其他情况),基本上没有办法复现,如果用户出了问题但是不反馈或直接不用了,对开发者或公司来说都是损失。
由于我这个项目比较小,只是一个迷你商城,所以不需要收集很复杂的数据,只需要知道有没有资源加载失败、哪行代码报错就可以了,市面上有很多现成的监控平台比如sentry,在这里我选择通过nodejs自己搭一个服务。
概述
我的项目是使用Vue2写的,所以本文主要是讲Vue相关的部署过程
1、部署后台服务(使用express)
2、收集前端错误(主要是Vue)
3、提交信息到后台分析源码位置及记录日志
js异常处理
这里可以看到,当js运行报错后,代码就不往下执行了,这是因为js是单线程,具体可以看看事件循环,这里不做解释
接下来看看使用异步的方式执行,可以看到没有影响代码的继续运行
那报错之后我们如何收集错误呢?
try catch
使用
try catch将代码包裹起来之后,当运行报错时,会将收集到的错误传到catch的形参中,打印之后我们可以拿到错误信息和错误的堆栈信息,但是try catch无法捕获到异步的错误可以看到
try catch是无法捕获到异步错误的,这时候就要用到window的error事件监听error事件
除了
window.addEventListener可以监听error之后,window.onerror也可以监听error,但是window.onerror和window.addEventListener相比,无法监听网络异常window.addEventListener
window.onerror
由于无法监听到,这里就不放图了
unhandledrejection
到目前为止,
Promise已经成为了开发者的标配,加上新特性引入了async await,解决了回调地狱的问题,但window.onerror和window.addEventListener,对Promise报错都是无法捕获可以看到,监听
window上的error事件是没有用的,可以每一个Promise写一个catch,如果觉得麻烦,那么就要使用一个新的事件,unhandledrejection其中,
reason中存放着错误相关信息,reason.message是错误信息,reason.stack是错误堆栈信息Promise错误也可以使用 try catch捕获到,这里就不做演示了
至此,js中
同步、异步、资源加载、Promise、async/await都有相对应的捕获方式vue异常处理
由于我的项目使用Vue2搭建的,所以还需要处理一下vue的报错
现在的项目基本上都是工程化的,通过工程化工具打包出来的代码长这样,上面的代码打包后运行
通过报错提示的js文件,查看后都是压缩混淆之后的js代码,这时候就需要打包时生成的
source map文件了,这个文件中保存着打包后代码和源码对应的位置,我们只需要拿到报错的堆栈信息,通过转换,就能通过source map找到对应我们源码的文件及出错的代码行列信息那我们怎么才能监听
error事件呢?使用Vue的全局错误处理函数
Vue.config.errorHandler在
src/main.js中写入以下代码现在打包vue项目
打包vue之后然后通过端口访问
index.html,不建议你双击打开,如果你没改过打包相关的东西,双击打开是不行的,可以通过vs code装插件live server,然后将打包文件夹通过vs code打开上报错误数据
经过上述的异常处理后,我们需要将收集到的错误进行整理,将需要的信息发送到后台,我这里选择使用ajax发请求到后端,当然你也可以使用创建一个图片标签,将需要发送的数据拼接到src上
这里我选择使用
tracekit库来解析错误的堆栈信息,axios发请求,dayjs格式化时间安装完成后在
src/main.js中引入tracekit、axios、dayjs上报Vue错误
如果你还需要其他的数据就自己加
打包vue之后然后通过端口访问
index.html,不建议你双击打开,如果你没改过打包相关的东西,双击打开是不行的,可以通过vs code装插件live server,然后将打包文件夹通过vs code打开现在去项目中看看发出去的请求参数是什么
可以看到我们需要的数据都已经收集到了,上报失败是肯定的,因为我们还没有写好接口
上报window错误
接下来在监听
window的error事件,也向后台发送一个错误上报请求搭建监控后台
创建一个文件夹,名字随便,然后在终端中打开文件夹,初始化npm
初始化完成后创建一个
server.js,这里我使用express进行搭建后端,source-map用于解析js.map文件,这些库后面会用到下好包之后在
server.js中输入以下代码,然后在终端输入nodemon server.js服务启动之后,访问本地的9999端口,查看是否生效,当看到屏幕上显示
Hello World!表示我们的后端服务成功跑起来了,接下来就是写错误的上传接口在这里我将为Vue和Window监控分别写一个接口(因为我懒得一个接口做判断区分,如果你觉得两个接口太麻烦,那你也可以自己优化成一个接口)
编写Vue错误上报接口
在
server.js中继续添加然后
nodemon会自动重启服务,如果你不是用nodemon启动的,那自己手动重启一下打包vue之后然后通过端口访问
index.html,不建议你双击打开,如果你没改过打包相关的东西,双击打开是不行的,可以通过vs code装插件live server,然后将打包文件夹通过vs code打开,通过live server运行,此时应该会报跨域问题设置允许跨域
可以自己手动设置响应头实现跨域,我这里选择使用
cors库此时重新运行后台,再观察
此时发现,解析map文件报错了,那是因为我们还没有上传map文件
在
server.js同级目录下创建一个uploads文件夹回到打包vue打包文件目录
dist,将js文件夹中所有js.map结尾的文件剪切到创建的文件夹中,如果你打包文件中没有js.map,那是因为你没有打开生成js.map的开关,打开vue.config.js,在defineConfig中设置属性productionSourceMap为true,然后重新打包就可以了为什么是剪切?如果真正的项目上线时,你把js.map文件上传了,别人拿到之后是可以知道你的源码的,所以必须剪切,或者复制之后回到dist目录删掉所有js.map
这时候我们再刷新网页,然后看后台的输出,显示
src/App.vue的第10行有错编写window错误上传接口
此时我们去vue项目中添加一个img标签,获取一张不存在的图片即可出发错误,由于不用解析,所以这里就不再上传
js.map了写入日志
错误上报之后我们需要记录下来,接下来我们改造一下接口,收到报错之后写一下日志
我需要知道哪一天的日志报错了,所有我在node项目中也下载
dayjs用来格式化时间此处的日志记录内容只是我自己需要的格式,如果你需要其他格式请自己另外添加
vue错误写入日志
window错误写入日志
和vue写入的方式差不多,存在优化空间
至此,收集错误,上报错误,写入日志已经全部完成。
其他
错误监控持久化运行在服务器
这个可以使用
pm2,在服务器上使用node全局安装pm2库自动上传js.map文件
如果每次打包后都手动复制
js.map文件的到uploads文件夹下,似乎有些麻烦虽然麻烦,但是我自己还是没有自动上传,原因是如果打包就自动上传,那么如果项目还未发布,但是文件已经替换掉之前的文件了,新版本未发布之前,vue的错误就无法解析了,当然,如果你每次上传都不删除以前的文件也是可以的
修改vue项目
在vue项目
src下创建一个plugin目录,新建一个UploadSourceMap.js,将下面的代码粘贴进去修改
vue.config.js主要是引入
UploadSourceMap,并且在configureWebpack => plugins下使用修改后台
修改
server.js,新增一个上传文件的接口然后现在重新打包,观察打包输出
最后
尽量是不要开启跨域,否则谁都能给发请求到后台,如果要开跨域,那需要做好判断,主域名不符合的直接返回404终止这次请求。
市面上的监控有很多,有些甚至能实现录制用户操作生成gif,本文只是实现一个基本的错误监控,如有错误请指出。
源码参考:https://github.com/liuxulin0626/error-monitor-demo
原文地址:https://juejin.cn/post/7383955685368086562
作者:用户不会像你这么操作的
如有错误,欢迎指正。
- 作者:90_blog
- 链接:https://blog.tri7e.com/article/bug_watch
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
