跳到主要内容

浏览器渲染流程与性能指标

🎨 性能优化的核心是缩短关键渲染路径、减少主线程工作,并围绕真实用户体验指标持续测量。

浏览器渲染流水线

  1. 解析 HTML,构建 DOM。
  2. 解析 CSS,构建 CSSOM。
  3. 合并 DOM 与 CSSOM,生成渲染树。
  4. Layout:计算元素几何位置与尺寸。
  5. Paint:生成绘制指令。
  6. Composite:合成图层并显示到屏幕。

JavaScript 可能阻塞 HTML 解析;样式表通常会阻塞渲染。defer 脚本在 HTML 解析完成后按顺序执行,async 下载完成即执行且顺序不确定。

重排、重绘与合成

  • Layout / Reflow:几何信息改变,代价通常最高。
  • Paint:外观改变但几何不变,例如颜色、阴影。
  • Composite:合成层变换,例如合适场景下的 transformopacity

⚠️ 不要把“使用 transform”机械等同于“永远更快”。过多合成层会增加显存、上传和合成成本。

强制同步布局

在写入样式后立即读取布局属性,浏览器可能被迫提前计算布局:

// 容易反复触发布局
for (const item of items) {
item.style.width = `${item.offsetWidth + 1}px`
}

// 批量读,再批量写
const widths = items.map(item => item.offsetWidth)
items.forEach((item, i) => {
item.style.width = `${widths[i] + 1}px`
})

常见布局读取包括 offsetWidthgetBoundingClientRect()getComputedStyle()

Core Web Vitals

  • LCP:最大内容绘制,反映主要内容加载速度;目标通常 ≤ 2.5 秒。
  • INP:交互到下一次绘制,反映页面响应性;目标通常 ≤ 200 毫秒。
  • CLS:累计布局偏移,反映视觉稳定性;目标通常 ≤ 0.1。

辅助指标:

  • TTFB:首字节时间
  • FCP:首次内容绘制
  • TBT:总阻塞时间,常用于实验室环境

优化策略

加载

  • 压缩资源并使用 HTTP 缓存、CDN。
  • 关键资源预加载,非关键资源延迟加载。
  • 图片提供正确尺寸、现代格式与 srcset
  • 拆分 JavaScript,减少首屏执行和第三方脚本。

运行时

  • 拆分长任务,给输入和渲染让出主线程。
  • 对大列表使用虚拟化。
  • 避免无意义的重复渲染、布局抖动和频繁序列化。
  • 将适合的计算移到 Web Worker。

稳定性

  • 为图片、视频、广告预留尺寸。
  • 避免在已有内容上方动态插入内容。
  • 使用合适的字体加载策略。

测量工具

  • Chrome DevTools Performance:主线程、火焰图、Layout 与 Paint。
  • Lighthouse:实验室诊断。
  • PerformanceObserver / web-vitals:真实用户监控。
  • DevTools Network:资源瀑布、缓存和优先级。
new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
console.log(entry.name, entry.duration)
}
}).observe({ type: 'longtask', buffered: true })

排查路径

  1. 明确是加载慢、交互卡顿还是视觉跳动。
  2. 用真实设备和弱网复现。
  3. 记录基线指标。
  4. 在时间线上定位瓶颈。
  5. 一次只验证一个假设。
  6. 上线后通过真实用户数据观察回归。