长效监控需轮询+事件驱动+状态聚合,将静态getter转为动态指标流;优先轮询performance.memory等低开销实时属性,用performanceobserver监听paint、lcp、longtask等事件,并绑定上下文防失真,辅以节流上报保障可持续性。

直接用原生 performance API 的 getter 属性(如 performance.memory、performance.timing、performance.navigation)无法建立真正长效的监控,因为它们多数是只读快照、不可监听、不随时间自动更新。长效监控必须靠主动轮询 + 事件驱动 + 状态聚合来实现,核心是把“静态 getter”变成“动态指标流”。
聚焦可轮询的实时状态 getter
不是所有 getter 都适合长周期采集,优先选择响应快、开销低、能反映运行态变化的属性:
-
performance.memory:仅 Chrome 支持,返回usedJSHeapSize、totalJSHeapSize、jsHeapSizeLimit,每 2–5 秒轮询一次即可观察内存泄漏趋势 -
performance.timeOrigin:固定值,不参与轮询,但可用于统一时间基线校准所有自定义打点 -
performance.now():虽非 getter,但它是高精度单调时钟,所有自定义耗时测量(如函数执行、渲染间隔)都应基于它,而非Date.now() -
performance.getEntriesByType('navigation')[0]:只在首屏有效,不适合长效;但可结合PerformanceObserver监听后续navigation类型条目,捕获 SPA 路由跳转带来的新导航上下文
用 PerformanceObserver 补齐 getter 的被动性缺陷
原生 getter 是“你问才有”,而 PerformanceObserver 能让浏览器在关键节点自动通知你,这是构建长效监控的关键拼图:
- 监听
'paint'类型,捕获first-paint和first-contentful-paint的首次触发,后续滚动/交互中再出现则忽略(避免重复) - 监听
'largest-contentful-paint',每次触发都记录元素 ID、渲染时间、是否在视口内,用于追踪 LCP 动态漂移 - 监听
'longtask',获取主线程阻塞详情(开始时间、持续时长、堆栈线索),比轮询performance.memory更早暴露卡顿风险 - 监听
'resource',过滤出慢资源(如duration > 3000),并关联其initiatorType(script/css/img),定位劣化来源
将 getter 数据与行为上下文绑定,避免指标失真
单独看 performance.memory.usedJSHeapSize 没意义,必须结合页面状态才能解读:
- 在路由切换前记录内存基线,切换后 1 秒再采一次,差值 > 5MB 且未回落,标记为潜在泄漏
- 用户滚动开始时启动计时器,滚动结束 500ms 后检查
performance.getEntriesByType('paint')中最新帧的startTime,计算滚动期间平均帧间隔 - 对每个
fetch或XMLHttpRequest手动打点(performance.mark('api-start-xxx')),再用performance.measure()关联响应时间,弥补resource条目中缺少业务语义的缺陷
轻量上报与防抖设计,保障长效可持续
长效 ≠ 全量上报。高频 getter 轮询会产生大量数据,必须做聚合与节流:
- 内存指标每 5 秒采样,但只在变化幅度 > 2% 或绝对增量 > 1MB 时才记录一条日志
- 使用
navigator.sendBeacon()上报,确保页面卸载前数据不丢失;若需更高可靠性,可先写入localStorage缓存,下次打开时补发 - 对同一类指标(如所有 LCP 变更)启用滑动窗口统计:每 30 秒汇总 P50/P90 值、最大偏移量、触发次数,压缩为单条结构化 JSON 上报
- 禁用调试环境下的采集逻辑(
location.hostname === 'localhost'),避免干扰开发体验










