📡 前端错误监控从零搭建:window.onerror 与 unhandledrejection 的完整实践

问题场景

线上用户反馈"页面白屏了",你本地怎么复现都不行;或者用户说"点按钮没反应",但你根本不知道报了什么错。没有错误监控的前端,就像蒙着眼睛开车------全靠用户当你的眼睛。

原因分析

前端错误主要分三类,捕获方式完全不同:

  1. 运行时错误 (同步/异步代码抛错)→ window.onerror
  2. Promise 未捕获拒绝unhandledrejection
  3. 资源加载失败 (图片/脚本/CSS)→ error 事件的捕获阶段

很多人只监听 window.onerror,结果 Promise 错误和资源错误全漏了。

完整监控方案

第一步:捕获运行时错误

js 复制代码
window.onerror = function (message, source, lineno, colno, error) {
  report({
    type: 'runtime',
    message,
    source,
    lineno,
    colno,
    stack: error?.stack,
    url: location.href,
    ua: navigator.userAgent,
    time: Date.now()
  });
  // 注意:返回 true 会阻止浏览器默认处理(如控制台报错),慎用
};

第二步:捕获 Promise 错误(最容易漏)

js 复制代码
window.addEventListener('unhandledrejection', (e) => {
  // e.reason 可能是 Error 对象,也可能是任意值(如字符串、对象)
  report({
    type: 'promise',
    message: e.reason?.message || String(e.reason),
    stack: e.reason?.stack,
    time: Date.now()
  });
  e.preventDefault(); // 可选:屏蔽控制台红色警告
});

第三步:捕获资源加载失败

js 复制代码
// 必须用捕获阶段(第三个参数 true),因为资源错误不会冒泡
window.addEventListener('error', (e) => {
  const target = e.target;
  if (target && (target.tagName === 'IMG' || target.tagName === 'SCRIPT' || target.tagName === 'LINK')) {
    report({
      type: 'resource',
      tag: target.tagName,
      src: target.src || target.href,
      time: Date.now()
    });
  }
}, true);

第四步:框架层兜底

Vue 3:

js 复制代码
app.config.errorHandler = (err, instance, info) => {
  report({ type: 'vue', message: err.message, stack: err.stack, info });
};

React: 用 Error Boundary 包裹,componentDidCatch 里上报。

第五步:上报策略(防刷爆后端)

js 复制代码
// 采样 + 去重 + 批量
let buffer = [];
function report(data) {
  buffer.push(data);
  if (buffer.length >= 10) flush();
}
function flush() {
  if (!buffer.length) return;
  // 用 sendBeacon,页面关闭也能发出;且不阻塞主线程
  navigator.sendBeacon('/api/error-report', JSON.stringify(buffer));
  buffer = [];
}
window.addEventListener('beforeunload', flush);

// 采样:只上报 10% 的重复错误,控制成本
if (Math.random() > 0.1) return;

进阶技巧

  • sourcemap 还原 :生产代码是压缩的,上报 error.stack 后,用 sourcemap 在服务端还原原始行号(webpack 配 devtool: 'hidden-source-map',map 文件不上传到 CDN)
  • 错误去重 :同一错误一天内只告警一次,按 message + source + lineno 做指纹
  • 白屏检测document.readyState 长时间非 completedocument.body 无子节点,主动上报

要点总结

  • 三类错误三种捕获姿势:onerror(运行时)、unhandledrejection(Promise)、捕获阶段 error(资源)
  • 框架错误要用各自的钩子(Vue errorHandler / React Error Boundary)
  • sendBeacon + 批量上报,页面销毁也不丢数据
  • 采样、去重、指纹告警,否则监控系统会被错误洪流淹没
  • sourcemap 只上线 map 文件到内网,别把源码泄露到 CDN
相关推荐
jarvisuni1 小时前
翻车了!GPT5.6接手Opus4.8的项目之后!
前端·人工智能·ai编程
雨田言炎2 小时前
十、QThread多线程
linux·服务器·开发语言·前端·qt
IT_陈寒2 小时前
Vite热更新失效?我的几个犯傻操作害我debug两小时
前端·人工智能·后端
晓得迷路了2 小时前
栗子前端技术周刊第 141 期 - Next.js 16.3、npm 安全事件、2026 CSS 现状调查报告结果...
前端·javascript·npm
2601_965798472 小时前
Launch Your Wellness App Fast: The Truth About Meditation Source Code
前端·macos·ios·objective-c·cocoa
周小董2 小时前
[1367]npm 安装 canvas 报错 node-gyp ERR
前端·npm·node.js
智脑API2 小时前
Codex config.toml check_for_update_on_startup 怎么关闭?离线环境与版本提醒排查
运维·服务器·前端
存在的五月雨3 小时前
前端布局-flex
前端
weixin_431600443 小时前
NestJS 入门(1):先搞懂 Module、Controller、Service
开发语言·前端·后端·nest.js