背景
目前公司没有 sentry, 打包后的代码也没有 souce-map文件, 出现线上问题, 比较难排查
案例:
现在在控制台拿到这样一段报错信息
chunk-libs.74f9af28.js:1
Uncaught TypeError: e is not a function
at chunk-libs.74f9af28.js:1:76904
at Array.forEach (<anonymous>)
at new v (chunk-libs.74f9af28.js:1:76876)
at 56d7 (app.42ce26c3.js:1:90547)
at b (mainLogin:197:5423)
at 0 (app.42ce26c3.js:1:96)
at b (mainLogin:197:5423)
at n (mainLogin:197:1174)
at Array.e [as push] (mainLogin:197:1037)
at app.42ce26c3.js:1:53
从上面的信息中, 我们能获取到如下信息
-
打包后文件的 hash, 以及文件的行, 列
-
报错的信息
-
报错的业务文件 mainLogin
操作步骤
1、 本地代码 拉取 线上发版的代码分支, 注意, git 分支的hash一定要是 发版的hash, 否则本地打包后的 source-map 会变化, 比如 2022-07-29 发版本 release 分支 对应的 git hash 是 e2955de
2、调整 vue.config.js 配置 productionSourceMap改为true
3、 本地 npm run build 打包, dist目录会存在 .map 的对应文件
4、本地创建一个 test-map 目录。用于执行 node 脚本
npm i source-map
5、app.js完整代码在文末, 根据日志调整 searchSource 里面的文件指向, 还有对应报错信息里面的 行, 列
6、 命令行运行 node app.js
7、根据错误信息, 从上往下进行分析, 报错信息是 错误日志栈, 最先调用的地方,最先报错, 日志从上往下分析
如果是 类库报错, 则更新类库
如果是业务代码报错, 则最先报错的地方应该是 src/views/xxx.vue 文件。 然后再去看对应的文件
从下面的输出判断
// {
// source: 'webpack:///src/store/index.js',
// line: 28,
// column: 23,
// name: 'Store'
// }
我们找到 项目中的 src/sotre/index.js 指向这里, 和上面的日志是一一对应的
完整代码
const fs = require('fs')
const sourceMap = require('source-map');
const readFile = function (filePath) {
return new Promise(function (resolve, reject) {
fs.readFile(filePath, { encoding: 'utf-8' }, function (error, data) {
if (error) {
console.log(error)
return reject(error);
}
resolve(JSON.parse(data));
});
});
};
// Find the source location
async function searchSource (filePath, line, column) {
const rawSourceMap = await readFile(filePath)
const consumer = await new sourceMap.SourceMapConsumer(rawSourceMap);
const res = consumer.originalPositionFor({
'line': line,
'column': column
});
consumer.destroy()
return res
}
searchSource('./chunk-libs.74f9af28.js.map', 1, 76904).then(res => {
console.log(res)
})
// {
// source: 'webpack:///node_modules/vuex/dist/vuex.esm.js',
// line: 427,
// column: 45,
// name: 'plugin'
// }
// ----- 分割
// searchSource('./chunk-libs.74f9af28.js.map', 1, 76876).then(res => {
// console.log(res)
// })
// {
// source: 'webpack:///node_modules/vuex/dist/vuex.esm.js',
// line: 427,
// column: 10,
// name: 'forEach'
// }
// =============
// searchSource('./app.40e8b854.js.map', 1, 90547).then(res => {
// console.log(res)
// })
// {
// source: 'webpack:///src/store/index.js',
// line: 28,
// column: 23,
// name: 'Store'
// }