前端监控解决什么

后端出了问题可以通过日志和指标定位,前端的问题却常常「只在用户那里发生」:某个机型白屏、某个页面按钮点了没反应、某个版本一上线报错率飙升。没有监控,这些全靠用户反馈,又慢又零散。

前端监控要做三件事:把错误接住、把现场还原、把信号变成告警。错误接住靠全局捕获,现场还原靠上报环境信息和用户操作路径,告警让团队在用户抱怨之前就发现问题。

一套完整体系包括错误监控、性能监控和行为埋点三层。三者的数据可以打通:同一个用户会话里,性能差、报错多、流失快,这些信号放一起看,才能定位真正的体验瓶颈。

没有监控的线上前端,等于在盲飞。
本文核心知识点
  • 全局捕获onerror 与 unhandledrejection。
  • sourcemap还原压缩代码堆栈。
  • 埋点性能与行为数据采集。
  • 上报通道、采样与降噪。
前端监控配图:蓝调抽象插画中多层发光同心圆核心向外辐射波浪流线,四周环绕半透明椭圆面板与圆点节点的科技场景
同心圆核心收集四面八方的信号,像监控平台汇总各处上报。

错误捕获:onerror 与 unhandledrejection

脚本运行时错误统一走 window.onerror,Promise 失败且没有 catch 时走 unhandledrejection。把这两个入口接住,大部分运行时错误就都有了兜底。

window.addEventListener('error', (e) => {
  monitor.report({
    type: 'js',
    message: e.message,
    file: e.filename,
    line: e.lineno,
    col: e.colno,
    stack: e.error ? e.error.stack : ''
  });
});

window.addEventListener('unhandledrejection', (e) => {
  monitor.report({ type: 'promise', reason: String(e.reason) });
});

注意 error 事件里的资源加载失败(图片、脚本、样式 404)也走这个入口,但它们的 e.target 是元素而不是 Error 对象,要单独区分类型,避免误报。

捕获之后还要能关:某些业务代码确实预期会抛错,可以用标志位或命名约定跳过,否则告警会被噪音淹没,慢慢就没人看了。

资源与网络请求监控

页面白屏最常见的原因是资源加载失败,尤其是 CSS 和脚本。资源监控监听 error 事件里 target 是 HTMLElement 的情况,记录 src 和标签类型。

window.addEventListener('error', (e) => {
  const el = e.target;
  if (el instanceof HTMLElement) {
    monitor.report({ type: 'resource', tag: el.tagName, src: el.src });
  }
}, true);

接口请求监控一般拦截 fetch 和 XHR:记录 url、方法、耗时、状态码和响应大小。成功率、平均耗时、P95 这些聚合指标,直接反映后端对前端的服务质量。

请求监控的代码要在业务脚本之前注入,才能覆盖所有请求。这也是为什么成熟的 SDK 都以最早加载的脚本形式引入。

sourcemap 错误还原

生产环境的 JS 都经过压缩混淆,报错堆栈只有一行压缩后的代码,基本没法定位。sourcemap 记录了压缩代码到源码的映射,用它能把行列号翻译回原始文件和函数。

做法是在构建产物里保留 .map 文件,但不直接暴露给浏览器下载,而是上传到监控平台。监控平台收到带行列号的错误后,用 sourcemap 离线还原出源码位置。

// webpack 配置
module.exports = {
  devtool: 'hidden-source-map',
  // hidden 表示 map 文件存在但不生成注释引用
};

还原的关键是版本对齐:sourcemap 必须和线上 JS 是同一次构建的产物,发布时要把版本号一起上报,否则还原出来的位置是错的。

性能与体验埋点

性能数据用 Performance API 获取:Navigation Timing 提供页面加载各阶段耗时,Resource Timing 提供每个资源耗时,Long Tasks 记录阻塞主线程的长任务。

window.addEventListener('load', () => {
  const nav = performance.getEntriesByType('navigation')[0];
  monitor.report({
    type: 'perf',
    ttfb: nav.responseStart - nav.requestStart,
    domContentLoaded: nav.domContentLoadedEventEnd - nav.requestStart,
    load: nav.loadEventEnd - nav.requestStart,
  });
});

体验指标 LCP(最大内容绘制)和 INP(交互响应)是用户感知的核心,可以用 PerformanceObserver 订阅。行为埋点则记录关键动作:点击、滚动、路由切换,把用户路径串起来,出问题时能回放现场。

埋点要克制,只埋能指导决策的事件。埋得过多既耗性能,也让分析无从下手。