要用 PerformanceObserver 监控长任务,必须在 <head> 内联脚本中早期注册,启用 buffered: true 捕获已发生条目,提取 startTime 和 duration 对齐时间,并节流上报避免连锁卡顿。

要用 PerformanceObserver 监控长任务,核心是早期注册、正确配置、关联上下文——不是等页面加载完再监听,而是抢在第一个长任务发生前就准备好。
必须在 内联脚本中注册 observer
长任务可能出现在 HTML 解析阶段、DOM 构建前,甚至首屏渲染之前。如果 observer 在 DOMContentLoaded 或 window.onload 之后才注册,那些早期卡顿就完全漏掉了。
- 把注册代码直接写在
<head><script>...</script></head>最顶部,不依赖任何外部资源或模块 - 避免用
async、defer或动态import()加载 observer 脚本 - 检查浏览器支持:
if ('PerformanceObserver' in window && 'longtask' in PerformanceObserver.supportedEntryTypes)
启用 buffered: true 才能捕获已发生的条目
buffered: true 是关键开关,它让 observer 能读取注册前已产生的 longtask 条目(比如解析 HTML、执行内联脚本时触发的)。
- 错误写法:
observer.observe({ entryTypes: ['longtask'] })→ 首屏长任务全丢 - 正确写法:
observer.observe({ entryTypes: ['longtask'], buffered: true }) - 不支持 buffered 的 polyfill 或降级方案无效,必须依赖原生 API
提取 startTime 和 duration 做时间对齐
每个 longtask 条目只提供 startTime(高精度时间戳)、duration(毫秒)、attribution?.containerType(如 script、iframe),没有函数名或调用栈。靠时间戳才能定位真实瓶颈。
立即学习“Java免费学习笔记(深入)”;
- 在用户关键操作前打标记:
performance.mark('user-click-start') - 上报时记录
entry.startTime和entry.duration,后端可比对是否落在某次操作前后 100ms 内 - 结合
entry.attribution?.containerType判断是否来自第三方 script 或嵌套 iframe,快速排除或聚焦范围
避免在回调里做重操作,节流上报
longtask 回调本身运行在主线程,若在里面发网络请求、序列化大对象或执行复杂计算,可能触发新的长任务,形成连锁卡顿。
- 上报逻辑用
setTimeout(..., 0)或queueMicrotask延后执行 - 生产环境做频率控制:例如每 500ms 合并一次数据,或只上报
duration > 100ms的严重项 - 不直接打印
console.warn到控制台,开发期可用,线上应关闭或替换为轻量日志



















