一、sourcemap是什么
source map:保存源代码映射关系的文件
1、作用
由于我们使用webpack去打包文件会生成bundle.js文件,都是混淆在一起,代码可能是一个或者多个文件组成,当报错的时候无法去定位到错误信息。
因此source-map记录了映射关系,可以帮助我们快速去定位问题
二、Webpack当中的source-map
1、如何配置?
devtool:‘source-map’
2、配置项可选的值
在webpack官网中有很多的配置,但也是基于以下五个去组合而成。
- source-map:产生.map文件
- eval:使用eval包裹模块
- cheap:不生成列信息
- inline:将.map作为datauUrl嵌入,不单独生成一个.map文件
- module:包含loader的map文件
- hidden:会正常生成map文件,但是不会有sourceMappingURL=main.js.map去关联文件
三、实践
1、前端监控
一个完成的前端监控系统的流程:
- 前端错误收集
- 前端上报错误信息堆栈到服务器
- 前端代码打包上线后将source-map文件上传到服务器
- 服务器接受错误并记录到日志当中
- 服务器根据日志和上传的source-map进行错误分析
这里实现一个简单的前端监控系统:
- 前端上报错误到服务器
- 服务器根据source-map去分析错误信息定位到问题
前端收集上传错误
import axios from 'axios'
// 上报错误
const fetchError = (error)=>{
axios.get('http://127.0.0.1:3000/error',{
params:{
error
}
}).then(res=>{
console.log(res)
})
}
// 收集错误
window.addEventListener('error',(e)=>{
fetchError(e.error.stack)
})
// 模拟错误代码
console.log(b)
利用Express搭建服务器
const express = require('express')
const {ananlyze} = require('./analysis')
const app = express()
// 跨域请求配置
app.use((req,res,next)=>{
res.header('Access-Control-Allow-Origin', "*");
res.header('Access-Control-Allow-Headers', 'Content-Type,Content-Length,Authorization,Accept,X-Requested-With');
res.header('Access-Control-Allow-Methods','PUT,POST,GET,DELETE,OPTIONS');
res.header('X-Powered-By', '3.2.1')
if(req.method === 'OPTIONS') {
res.send(200);
} else {
next();
}
})
app.get('/error',async (req,res)=>{
console.log('开始解析错误信息')
let errorStack = req.query.error
const data = await ananlyze(errorStack)
console.log(data)
res.send(data)
})
app.listen(3000,()=>{
console.log('run at http://127.0.0.1:3000')
})
服务器根据错误和source-map去分析定位
// 引入堆栈分析工具
const StcakTracey = require('stacktracey')
// 引入source-map解析工具
const SourceMap = require('source-map')
const fs = require('fs')
const path = require('path')
const readFile = (fielPath)=>{
return new Promise((resolve,reject)=>{
fs.readFile(fielPath,{flag:'r'},(error,data)=>{
if(error) reject(error)
else resolve(data)
})
})
}
const ananlyze = async (errorSatck)=>{
// 解析错误栈信息
const traceyInfo = new StcakTracey(errorSatck)
// 获取错误信息位置
const {line,column} = traceyInfo.items[0]
// 读取sourcemap文件
const sourceMapFileContent = await readFile(path.resolve(__dirname,'../dist/main.js.map'))
// 生成SourceMapConsumer实例
const consumer = new SourceMap.SourceMapConsumer(JSON.parse(sourceMapFileContent))
// 源代码错误信息位置
const originalPosition = (await consumer).originalPositionFor({
line,
column
})
// 获取源代码内容
const sourceContent = (await consumer).sourceContentFor(originalPosition.source)
return {
sourceContent,
...originalPosition
}
}
module.exports = {
ananlyze
}