前端定位线上问题的多种方案(不依赖 Sentry) 🛠️
一、构建时注入调试信息 🔧
1. 注入版本信息与 Git 提交哈希
Webpack 配置:
// webpack.config.js
const webpack = require('webpack');
const gitRevision = require('child_process').execSync('git rev-parse --short HEAD').toString().trim();
module.exports = {
plugins: [
new webpack.DefinePlugin({
__VERSION__: JSON.stringify(`v1.0.0-${gitRevision}`)
})
]
};
代码中使用:
console.log('当前版本:', __VERSION__);
// 输出:当前版本:v1.0.0-3a5b7d9e
优势:
- 精准定位代码版本,结合 Git 历史快速回溯问题
- 无需第三方工具,纯前端实现
2. 生成 Source Map 并选择性部署
Webpack 生产配置:
// webpack.config.js
module.exports = {
devtool: 'hidden-source-map', // 生成 Source Map 但不暴露给浏览器
output: {
sourceMapFilename: '[file].map[query]'
}
};
调试流程:
- 构建时生成
.map
文件,但不上传至 CDN - 报错时通过行号/列号(如
main.js:123:45
) - 本地使用
source-map
库解析错误位置:npx source-map analyze main.js.map --line 123 --column 45
优势:
- 安全:不暴露源码到生产环境
- 精准:还原压缩代码到源码位置
二、浏览器端主动捕获与上报 🌐
1. 全局错误监听
基础代码:
window.addEventListener('error', (e) => {
const errorInfo = {
msg: e.message,
file: e.filename,
line: e.lineno,
col: e.colno,
stack: e.error?.stack,
version: __VERSION__ // 构建时注入的版本
};
// 上报到自有API
fetch('/api/log-error', {
method: 'POST',
body: JSON.stringify(errorInfo)
});
});
增强方案(Promise 错误):
window.addEventListener('unhandledrejection', (e) => {
console.error('Unhandled Rejection:', e.reason);
});
2. Console 日志重定向
捕获所有 console.log
:
const originalConsoleLog = console.log;
console.log = (...args) => {
originalConsoleLog(...args); // 保持原功能
sendToServer('log', args); // 自定义上报
};
三、动态调试模式开关 🔌
1. URL 参数控制调试模式
代码示例:
const urlParams = new URLSearchParams(location.search);
const debugMode = urlParams.has('debug');
if (debugMode) {
localStorage.setItem('debug', 'true'); // 持久化调试状态
console.log('调试模式已开启');
}
// 根据调试模式加载不同资源
if (debugMode) {
import('./src/dev-tools.ts'); // 加载调试工具
}
安全措施:
- 后端校验参数权限(如特定IP或Token)
- 生产环境默认隐藏调试入口
2. 环境变量区分构建模式
Vite 配置:
// vite.config.js
export default defineConfig(({ mode }) => ({
define: {
__DEBUG__: mode === 'development' // 开发模式下启用调试
}
}));
代码中使用:
if (__DEBUG__) {
console.log('当前为调试模式,敏感操作已禁用');
}
四、本地 Source Map 调试方案 🔍
1. 浏览器直接关联本地源码
步骤:
- 构建时生成
source-map
- 在 Chrome DevTools 中配置:
- 打开 Sources 面板 → Overrides
- 映射网络资源到本地文件系统
效果:
2. VS Code 调试生产代码
配置 .vscode/launch.json
:
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Debug Production",
"url": "http://localhost:3000?debug",
"webRoot": "${workspaceFolder}/src",
"sourceMaps": true,
"sourceMapPathOverrides": {
"webpack:///./*": "${webRoot}/*"
}
}
]
}
五、方案对比与选型建议 📊
方案 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
构建注入版本 | 所有项目 | 无第三方依赖,快速定位版本 | 需自行实现错误收集 |
Source Map 解析 | 需要精准定位生产错误 | 安全可靠,还原源码位置 | 需手动管理 .map 文件 |
全局错误捕获 | 自有错误监控系统 | 完全可控,数据私有 | 需后端支持,开发成本较高 |
动态调试模式 | 紧急问题排查 | 灵活开关,不影响普通用户 | 存在安全风险,需严格权限控制 |
浏览器 Overrides | 前端开发者本地调试 | 直接修改生产代码,实时生效 | 仅限本地使用,无法团队协作 |
六、终极总结 🎯
「构建时埋点 + 浏览器捕获 + 动态调试」三位一体:
- 通过构建工具注入版本和 Source Map,建立代码与报错的精确映射
- 利用全局错误监听实现自主上报,摆脱对 Sentry 的依赖
- 结合 URL 参数动态开启调试模式,安全高效排查问题
一句话价值:
无需依赖 Sentry,通过前端工程化手段打造自闭环的线上问题定位体系,让每一次报错都“有迹可循、有版可查”。 🔍🚀