📡 前端错误监控从零搭建: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
相关推荐
xy345342 分钟前
Axure 9.0 中继器核心结构
前端·ui·html·axure·原型·产品设计
老王以为1 小时前
走进 AI Agent 第四篇(上):知识获取管道——RAG 基础
前端·人工智能·全栈
夏天要喝冰可乐1 小时前
一处写作,多平台分发:我给掘金做了一款开源 Chrome 插件
前端·chrome·vibecoding
货拉拉技术1 小时前
货拉拉开源Hadice:安卓 & 鸿蒙桌面调试工具
前端
程序猿DD2 小时前
OctaFuse Gateway 2.11.0:流式请求优化、用户折扣策略与错误契约升级
前端·后端
尾善爱看海2 小时前
《JavaScript 数组操作全攻略:12 类 API + 30 个实战场景 + 20 个避坑指南》
前端·javascript·面试
计算机魔术师2 小时前
Anthropic 估值冲 4 万亿,但企业客户已经偷偷换了便宜模型
前端
王六米。2 小时前
RAG知识库建设 文档解析 切分与索引如何衔接
服务器·前端·网络·企业数字化转型·智钳智能盒子
名字还没想好☜2 小时前
React 文件上传实战:预览 URL 回收、多文件逐个进度与拖拽放置区踩坑
前端·react·next.js