必须加第三个参数true,因为资源错误事件从document向下冒泡,只有捕获阶段监听才能确保捕获所有子元素抛出的error;否则window层收不到,导致监控上报为空。

document.addEventListener('error', handler, true) 为什么必须加第三个参数 true
不加 true 就捕不到图片、脚本、样式表的加载失败。浏览器中资源错误(如 <img src="404.png">)触发的是原生 Event,它从 document 向下冒泡,但中间节点(比如 div、section)可能拦截或没绑定监听,导致 window 层收不到。只有在捕获阶段(即从 document 开始向下传递时)监听,才能确保第一时间拿到所有子元素抛出的 error。
常见错误现象:只写 document.addEventListener('error', handler),结果监控上报里几乎全是空数据——不是没失败,是根本没捕到。
- 必须用
true,不能省略;false 或 undefined 等价于不设,等于白监听 - 不要混用
window.onerror来捕资源错误,它对跨域资源只报"Script error.",毫无诊断价值 - 判断是否为资源错误:检查
e.target是否存在,且'src' in e.target || 'href' in e.target - 排除 JS 运行时错误:加条件
!(e instanceof ErrorEvent),因为资源错误是普通 Event,而 JS 报错才是 ErrorEvent
如何区分“真失败”和“假阳性”上报
CDN 跨域资源失败时,浏览器出于安全限制不暴露真实状态码和 URL,只给一个空 e.target.src 和模糊错误。直接上报会污染数据,把“跨域脚本被拦截”当成“资源 404”,误导运维排查方向。
真正可用的过滤逻辑是组合判断:
- 若
e.target.localName === 'script'且e.target.src以https://cdn.example.com/开头 → 记为“CDN 脚本加载异常”,不计入 404 指标 - 若
e.target.localName === 'img'且e.target.src是相对路径(如/assets/logo.png)→ 才归为“业务资源失败”,需告警 - 动态插入的资源(如
document.createElement('script').src = url)不会出现在 HTML 源码里,得靠运行时维护一个window.__pendingResources = new Set()手动登记、匹配、清理 - 对
<link rel="stylesheet">,还要补充检查document.styleSheets中对应 sheet 的cssRules.length === 0,避免 CSS 解析失败漏报
performance.getEntries() 怎么补全 onerror 漏掉的失败
performance.getEntries() 本身不报告失败,但它能告诉你“哪些资源本该出现却没出现”。这个差集法是唯一能发现 HTTP 200 但内容损坏(比如 CDN 返回了 HTML 错误页)的手段。
关键执行时机和过滤逻辑:
- 只在
window.addEventListener('load', () => { ... })里调用,确保所有同步/异步资源通道已关闭 - 过滤
entryType === 'resource',提取name(即完整 URL),去重后生成已加载集合 - 遍历 DOM 获取所有
document.querySelectorAll('script[src], img[src], link[href]')的 URL,构成应加载集合 - 取差集:应加载 − 已加载 = 疑似失败资源;但要剔除那些带时间戳参数(如
?t=123)或动态拼接的 URL,它们无法静态比对 - 注意:该方法无法识别
import()动态模块失败,ESM 必须用try/catch单独兜底
监控脚本自身不能成为首屏瓶颈
放在 里的监控代码如果体积大、有 DOM 查询、发同步请求,会直接拖慢 FCP。实测超 1.5KB 压缩后代码会让低端安卓机首屏延迟 30ms+。
- 必须内联,禁止外链;压缩后严格 ≤ 1.5KB,删掉所有注释、空格、console
- 禁止任何
document.querySelector或document.getElementById,DOM 查询在load前不可靠且耗时 - 上报只用
navigator.sendBeacon(),禁用fetch或XMLHttpRequest(会阻塞页面卸载) - 不监听
PerformanceObserver的resource类型——每加载一个资源就新建对象,在低端机上引发 GC 频繁卡顿 - 全局变量用
window.__errMonitor = { pending: [], sent: 0 }这种极简结构,避免深拷贝或序列化开销
最易被忽略的是:差集计算必须在 load 后立刻执行,但上报要节流。同一秒内多个失败只合并发一次 Beacon,否则弱网下大量小请求反而压垮上报服务。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











