前言
众所周知,Sentry是一款实时的错误监控和性能监控工具,可以帮助开发者快速定位应用程序中的问题。
对于前端开发者而言,Sentry配合编译产物 source-map 可以精准地映射线上代码报错到源码位置。但是,不知道大家在使用qiankun时遇到过这个问题没有,子应用在发生报错后,通过 source-map 映射出的源码位置却完全不正确?
解决思路
调研Sentry的sdk发现,其提供了方法可以在上报信息前改变数据内容,如果能拿到正确的信息数据再上传即可解决问题。
那怎么拿到正确的信息呢?首先有一点是明确的,也是我写的解决方案的前提条件,编译打包后的js文件不管看起来多大,其本质是一行代码。那只要我能拿到正确的列数据就能解决这个问题了。
解决方案
- 在代码中注册sentry,打印sentry提供的报错信息,然后项目中进行事件抛错。
注册sentry
import * as Sentry from "@sentry/react";
Sentry.init({
// dsn等相关配置
beforeSend(event) {
console.log(event)
return event;
});
抛错代码:
<div
style={{ display: 'none' }}
onClick={() => { throw new Error('sentry test2'); }}
>
sentry2
</div>
- 在页面上触发报错。建议这里在本地跑项目拿到抛错的光标位置。
- 找到sentry抛错信息栈的最后一条数据
可以看到sentry给的colno是56909,这就是打包后的js中报错位置的列信息。
- 接下来用浏览器打开上面的filename文件,将文件内容全部拷贝到vscode中,然后全局搜索抛错文案并把光标放到步骤2中的位置,此时能看到报错真正的列信息。
- 计算偏移量,sentry给出的数据是56909,而通过js找到的数据是56265,偏移量是644。那我们在上传时做一个减法即可。
import * as Sentry from "@sentry/react";
Sentry.init({
// dsn等相关配置
beforeSend(event) {
event.exception.values = event.exception.values.map((item: any) => {
if (item.stacktrace) {
const {
stacktrace: { frames },
...rest
} = item;
frames[frames.length - 1].colno -= 644;
return {
...rest,
stacktrace: {
frames,
},
};
}
return item;
});
return event;
},
});
至此,问题得到了完美解决,我在不同的子应用甚至不同的微前端项目中反复论证,偏移量都是644。
总结
虽然解决了这个问题,但方法有点复杂,不知道是否有其他简单点方式。从最终结论猜测造成这个现象的原因,大概是因为子应用需要实现一些协议来连接Qiankun的主应用,所以打包时会注入一些代码,而且这多出来的代码量是固定的。