性能调试实战:Performance / Lighthouse
本节目标
- 会用「火焰图」的思路定位耗时点(用一段 Node 代码模拟分析)
- 会用 Lighthouse 生成审计报告
- 建立「测量 → 定位 → 修复 → 复测」的闭环工作流
Performance 面板(录制 → 分析):
① 打开 Performance,点录制,复现问题(交互/滚动/加载),停止
② 看主线程火焰图(Main):长条色块 = 长任务(>50ms 标红)
③ 点击色块看是什么函数(JS 执行 / 样式 / 布局 / 绘制)
④ 结合 Network(请求瀑布)、Timings(指标时间线)判断瓶颈火焰图怎么看:X 轴=时间,Y 轴=调用栈(上层调用下层);最宽的色块=最大耗时点,从它入手。颜色含义:蓝=HTML/CSS 解析、紫=JS 执行、绿=绘制、黄=布局。
常见问题模式:紫=JS 长任务(拆片/Worker);黄=频繁布局(读改写分离);绿=绘制过重(简化样式/分层);网络等待长=请求慢(缓存/CDN/预加载)。
下面这段 Node 代码模拟「分析火焰图」:给你一堆带耗时的任务,找出「长任务」并定位最慢的那个——这正是 Performance 面板在背后干的事:
// 运行环境:Node.js 14+
// 步骤:node brw-l16.js
// 它会从一组任务中找出 >50ms 的长任务,并报告最耗时的是哪一个(模拟火焰图定位)
// 模拟某次录制的「主线程任务列表」:{ name, duration(ms) }
const tasks = [
{ name: 'parseHTML', duration: 12 },
{ name: 'styleRecalc', duration: 8 },
{ name: 'bigJSON.parse', duration: 220 }, // 长任务!
{ name: 'layout', duration: 35 },
{ name: 'paint', duration: 18 },
{ name: 'eventHandler', duration: 95 }, // 长任务!
{ name: 'composite', duration: 6 },
]
const LONG_TASK = 50
const longOnes = tasks.filter(t => t.duration > LONG_TASK)
console.log('检测到的长任务(>50ms):')
for (const t of longOnes) console.log(` ⚠️ ${t.name}: ${t.duration}ms`)
const worst = tasks.reduce((a, b) => b.duration > a.duration ? b : a)
console.log('最耗时任务(优先优化):', worst.name, worst.duration + 'ms')
console.log('建议:把', worst.name, '这类重活用 Web Worker 或分片处理')Lighthouse(一键审计):Performance / Accessibility / Best Practices / SEO 四维度打分,给出「机会」与「诊断」列表(未用预加载、图片未压缩、CLS 超限等)。适合整体体检,发现问题后再用 Performance 精确定位。
内存泄漏排查:录制堆快照 → 操作页面 → 再录快照 → 对比,找「该回收却还在增长」的对象(未移除监听器、闭包 hold 大对象、定时器未清、全局误挂)。
实战工作流:
1. Lighthouse 体检 → 拿到嫌疑点清单
2. Performance 录制 → 定位具体函数/阶段(火焰图最宽块)
3. 修复后复测对比(量化:LCP 3s → 1.8s)
4. 真实用户监控(RUM)长期观察名词解释
火焰图(Flame Chart):把「调用栈随时间变化」画成高低错落的色块图,用来定位性能瓶颈。方法/读法:X 轴是时间(从左到右),Y 轴是调用栈深度(上调用下),最宽的块 = 最耗时,点进去看是哪个函数。它是 Performance 面板的核心视图,名字来源于「色块像火苗」。
长任务(Long Task):见 brw-l10 名词卡。在调试语境下,它的「识别方法」就是火焰图里标红(>50ms)的色块,或 longtask 性能条目。定位到长任务后,下一步是「拆分」或「丢给 Worker」。
Lighthouse:Google 提供的「网页体检工具」,自动跑一遍并打出多维度分数 + 优化建议。方法:Chrome DevTools 里点 Lighthouse 标签 → 选维度 → 生成报告。它适合「先找问题」,不适合「精确定位到某行代码」(那要用 Performance)。
课后练习
练习 1:Performance 火焰图里,你看到某次交互后有一长条黄色密集小色块,紧随其后是一段卡顿。最可能是哪类问题?怎么查?
答案:黄色代表「布局(Layout)」,密集黄色小块常是布局抖动(Layout Thrashing)——在循环里反复「写样式又读几何」,每次读都强制同步布局。查法:在代码里搜循环中的
offset*/getBoundingClientRect/scrollHeight等读取,配合「先读后写」原则重构(见 brw-l6)。Performance 面板里这类操作会显示大量紫色/黄色交错的强制布局标记。
练习 2:为什么「修完性能问题后必须复测」,而不能只凭感觉说「应该快了」?
答案:性能优化容易陷入「自欺」——你改了代码,主观觉得顺了,但可能只是某次偶然不卡。复测能给出可量化的前后对比(LCP 从 3s 到 1.8s、长任务从 5 个到 1 个),既验证有效,也避免「改了反而更慢」没发现。而且真实用户设备千差万别,单凭本地感觉不可靠,需要 RUM 长期监控。
总结
调试这节,我愿你建立的工作流不是「凭直觉改代码」,而是**「测量 → 定位 → 修复 → 复测」的闭环**。火焰图和 Lighthouse 不是装饰品:Lighthouse 负责「体检报告」(告诉你哪里可能病了),Performance 火焰图负责「精准开刀」(告诉你最宽的那个块是哪个函数)。很多人性能优化的悲剧,是「没测就改、改完没复测」——结果可能改对了,也可能改得更慢却浑然不知。把性能当成工程问题而非玄学,靠的就是这套可量化、可复现的流程。前面你学的每一个优化点(缓存、合成、分片、Worker),最终都要在这套流程里被「证明有效」才算数。