Performance API 通过 PerformanceObserver 主动监听 paint、LCP、CLS、longtask 等事件并结合业务埋点与多维度上下文判定性能异常,捕获后结构化上报。

Performance API 本身不直接“抛出异常”,但它能精准识别并暴露前端运行中的性能异常事件——即那些违背用户体验基准、超出合理阈值的性能退化行为。捕捉的关键不是等错误发生,而是主动监听浏览器内核派发的性能信号,并结合业务逻辑判定是否构成“异常”。
监听浏览器原生性能事件类型
PerformanceObserver 是捕获性能异常事件的核心机制,它以非阻塞方式接收浏览器自动记录的性能条目(PerformanceEntry)。需重点监听以下几类:
-
paint:获取首次绘制(FP)、首次内容绘制(FCP),延迟过高(如 FCP > 3s)即属渲染异常 -
largest-contentful-paint:LCP 超过 2.5s 表明核心内容加载严重滞后 -
layout-shift:单次 CLS > 0.1 或累积 CLS > 0.25,说明页面存在明显布局抖动 -
longtask:主线程连续占用 ≥50ms 的任务,是卡顿的直接证据 -
first-input:FID > 100ms 意味着用户首次交互响应已失敏 -
resource:资源 duration > 3000ms 或 status ≠ 200,提示加载失败或超时
示例:统一注册观察器
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach(entry => {
if (entry.entryType === 'longtask' && entry.duration > 100) {
console.warn('长任务异常:', entry.startTime, '持续', entry.duration, 'ms');
reportPerformanceAnomaly({ type: 'longtask', duration: entry.duration });
}
if (entry.entryType === 'layout-shift' && entry.value > 0.1) {
console.warn('布局偏移异常:', entry.value);
reportPerformanceAnomaly({ type: 'cls', value: entry.value });
}
});
});
observer.observe({ entryTypes: ['paint', 'largest-contentful-paint', 'layout-shift', 'longtask', 'first-input', 'resource'] });结合时间戳与自定义标记识别业务级异常
单纯依赖系统事件不够细粒度。可通过 performance.mark() 和 performance.measure() 主动埋点,定位具体环节的耗时异常:
- 在关键操作前打点:
performance.mark('api-fetch-start') - 在数据处理完成时再打点:
performance.mark('api-fetch-end') - 计算耗时:
performance.measure('api-fetch-total', 'api-fetch-start', 'api-fetch-end') - 获取结果:
performance.getEntriesByName('api-fetch-total')[0]?.duration - 若该值持续 > 2000ms,即可判定为接口响应异常(即使 HTTP 状态码正常)
判定异常需叠加上下文,而非孤立看单点数值
一次 LCP 偏高可能是网络抖动,但若同时满足以下条件,则构成可信异常:
- 过去 5 秒内出现 ≥2 次
longtask> 80ms - 当前页面
cls累计值突破 0.2 且仍在增长 - 最近 3 次
first-input延迟均值 > 120ms - 至少 2 个关键图片资源
duration> 5000ms
这类组合判断可大幅降低误报率,也更贴近真实用户感知。
异常捕获后需立即结构化上报,而非仅 console
捕获到异常后,应提取关键字段打包上报(建议用 navigator.sendBeacon):
-
type: longtask / cls / lcp / fid / resource_timeout -
value: 具体数值(ms 或分数) -
url: 当前页面 URL -
ua: 浏览器与设备信息 -
timestamp:performance.timeOrigin + performance.now()精确时间戳 -
context: 是否在首屏、是否触发过降级、是否有未处理 Promise rejection
不复杂但容易忽略


















