DevTools 长任务调试
用 Performance 面板复现交互卡顿,定位主线程长任务,再通过火焰图把阻塞归因到 JavaScript、Layout/Paint、序列化或其他同步工作并验证拆分效果。
#debug
#growing
#frontend
#browser
#chrome-devtools
[!info] related notes
- 所属 MOC: DevTools Performance MOC
- 前置概念: 长任务优化, 浏览器时间切片与协作式调度
- 读图: 火焰图
- 上位排障: 页面卡顿排查路线
DevTools 长任务调试
症状
- 点击后长时间没有视觉响应;
- 输入卡顿;
- 滚动掉帧;
- 某次交互明显“冻结”主线程。
第一步:录制真实交互
不要只录页面空闲状态。
记录:
- 开始 Performance recording;
- 执行真实卡顿动作;
- 停止;
- 先在时间轴定位用户输入到下一次画面更新之间的阻塞段。
第二步:确认是不是主线程长任务
长任务只是线索,继续看它与用户交互的时间关系。
一个 200ms 任务发生在后台空闲阶段,用户未必感知;一个 80ms 任务正卡在输入处理链路上,可能更重要。
所以优化目标不是“消灭所有红块”,而是减少关键交互路径上的 blocking time。
第三步:展开火焰图
把长任务分到真正的工作类型:
- JavaScript function / framework work;
- style recalculation;
- layout;
- paint/composite;
- JSON parse/serialize;
- 大循环/数据转换;
- third-party script。
不要只看 top-level task 名称。
第四步:找到调用来源
对于 JavaScript:
- 展开 call stack;
- 看具体 function / script;
- 必要时回 Sources;
- 结合 source map 找回源码。
对于 Layout/Paint:
继续检查是谁在同一交互中触发大量 DOM/style 变化。
第五步:按根因修复
常见方向:
- 大同步计算拆分;
- 避免重复 work;
- 降低 render/layout 范围;
- virtualize 长列表;
- 将可延迟工作移出关键交互;
- 必要时 Web Worker;
- 移除/延后第三方脚本。
修复方式必须由证据决定。
第六步:复录验证
修复后用相同 interaction 再录一次,比较:
- blocking task 时长;
- interaction latency;
- flame chart 工作量;
- frame/visual update。
没有复录,就无法证明优化真的命中瓶颈。
迁移检查
场景:点击“展开全部”后页面冻结 600ms。
闭卷完成:
- 怎样录制最有意义的 trace?
- 发现 500ms JS task 后为什么不能直接说“React 慢”?
- 怎样从 flame chart 继续找到真正函数?
- 如果主要时间在 Layout,而不是 JS,应改变什么排查方向?
- 修复后要比较哪些证据?