有效录制需:打开DevTools→切Performance→点圆形按钮(或Cmd/Ctrl+E)→立即执行目标操作→停止;务必用无痕窗口禁扩展,勾选Memory和Web Vitals,禁用缓存需在Network面板单独设置。

直接用 Chrome DevTools 的 Performance 面板录制,别信“自动监控脚本”或第三方封装——它本身已足够精准、可控,且时间轴对齐真实用户行为。
怎么启动一次有效录制
打开 DevTools → 切到 Performance 面板 → 点击左上角圆形录制按钮(或按 Cmd+E / Ctrl+E)→ 执行你要测的操作(比如点击按钮、触发路由跳转、滚动到底部)→ 再点停止。关键不是“录多久”,而是“操作是否覆盖目标路径”。
- 避免空等:录制开始后立刻操作,不要等页面“看起来加载完了”再点,否则会漏掉首屏关键帧
- 禁用扩展:某些广告拦截或调试插件会注入脚本,干扰主线程耗时,录制前开无痕窗口更干净
- 勾选
Screen capture仅在需要验证视觉卡顿(如丢帧、闪烁)时启用,它显著增大录制体积且不参与 JS/渲染分析
为什么录出来的火焰图里找不到 parseHTML 耗时
因为默认录制不捕获 HTML 解析器底层事件。gumbo_parse() 或 htmlparser2.parse() 这类函数调用不会自动出现在主线程堆栈中——它们被浏览器内核优化进 C++ 层,只暴露为 Parse HTML 这一聚合任务。
- 想定位解析瓶颈,得结合
PerformanceObserver监听longtask,并手动打标:performance.mark('parse-start')在 DOM 操作前,performance.mark('parse-end')在document.body可访问后 - 若用流式解析(如
htmlparser2.WritableStream),ontext回调里引用了完整 HTML 字符串,会导致内存驻留,火焰图上看不出,但内存面板里Detached DOM会持续增长 - SPA 场景下,
navigation类型记录只在首次加载有效;后续路由需手动performance.measure('route-change', 'nav-start', 'nav-end')才能关联 LCP/FID
录制参数选哪些才不误导判断
默认配置(60fps、JS Profile 开、Screenshots 关)适合大多数场景,但以下三项必须按需调整:
立即学习“前端免费学习笔记(深入)”;
-
Memory勾选:否则看不到解析过程中的内存抖动,而DOM Nodes和JS Heap突增常是解析器递归过深或事件监听器泄漏的信号 -
Web Vitals勾选:它把 FCP/LCP/INP 映射到时间轴具体位置,比人工数帧可靠得多 -
Disable cache在 Network 标签页里单独勾选,而非依赖 Performance 面板设置——否则静态资源可能从内存读取,掩盖真实网络阻塞
常见误判:LCP 时间戳为什么总对不上火焰图
因为 LCP 报告的是 largest-contentful-paint 回调触发时刻,而火焰图显示的是该元素 layout + paint 完成的合成时间,二者差值常达 1–3 帧。尤其当 LCP 元素是图片且未设置 decoding="async",解码会阻塞合成线程,但 Performance 面板默认不展开 Raster 子项。
- 展开
Rendering区域 → 找到对应帧 → 点击Layer Paints查看该图片是否在Raster阶段被拆成多块绘制 - 若发现
Parse HTML后紧跟着长Layout,检查是否有<table>/<tr>嵌套断裂(如<tr>没闭合),这会让 Blink 强制重排整个表格结构 - 别依赖
event.timeStamp计算 delta:它在 tab 切换后可能倒流,一律用performance.now()对齐时间轴
真正难的不是录,而是把 Parse HTML、Layout、Raster 三段耗时和代码里的 mark/measure 对齐——一旦错位,所有优化都白调。



















