Featured image of post 优化浏览器渲染管道(关键路径)Featured image of post 优化浏览器渲染管道(关键路径)

优化浏览器渲染管道(关键路径)

通过防止布局颠簸和优先考虑渲染阻塞脚本位置来最大限度地缩短启动时间。

介绍

关键渲染路径 (CRP) 是浏览器执行的将 HTML、CSS 和 JavaScript 转换为屏幕上可见像素的步骤序列。优化此管道直接影响第一内容绘制 (FCP)最大内容绘制 (LCP)。本文详细介绍了每个 CRP 阶段——DOM 构建、CSSOM 构建、渲染树、布局、绘制和合成——并提供了可行的优化策略。


第一阶段:DOM 构建

当浏览器接收到 HTML 字节时,它:

  1. 字节→字符:将原始字节解码为字符
  2. 标记化:将字符转换为标记(StartTagEndTag 等)
  3. Lexing:将令牌转换为节点
  4. DOM Tree:构建保留父子关系的节点树
<!-- This HTML produces a DOM tree with html > head + body > h1 + p -->
<!DOCTYPE html>
<html>
<head><title>Page</title></head>
<body>
  <h1>Hello</h1>
  <p>World</p>
</body>
</html>

优化:最小化 HTML 大小,通过正确的服务器配置尽早交付,并使用 流式传输(例如 Transfer-Encoding: chunked)。


第 2 阶段:CSSOM 构建

默认情况下,CSS 是渲染阻塞的。浏览器在渲染之前必须下载并解析所有CSS。 CSS 字节与 HTML 经历相同的转换管道,生成 CSS 对象模型 (CSSOM)

body { font-size: 16px; }
h1 { color: blue; }

每个 CSS 规则都与选择器进行匹配,并在此阶段计算特异性。

优化

  • 直接在 <head> 中内联关键 CSS 以获取首屏内容
  • 使用 media="print"loading="lazy" 推迟非关键 CSS
  • 缩小并使用 tree-shaking 删除未使用的 CSS

第三阶段:渲染树

渲染树结合了 DOM 和 CSSOM — 它只包含可见元素。排除具有 display: none<head> 子元素的元素。每个渲染树节点都包含其计算的样式。

DOM       CSSOM
 |          |
 +----+-----+
      |
  Render Tree
 (visible nodes + computed styles)

第四阶段:布局(回流焊)

浏览器计算每个渲染树节点的几何(位置和大小)。这是从视口开始的自上而下传递。具有基于百分比的宽度、flexboxgrid 的元素要求浏览器计算相对于其容器的大小。

布局抖动的原因

重复强制同步布局 - 在编写样式后读取布局属性(例如 offsetHeight) - 导致浏览器在单个框架中多次重新计算布局

// ❌ Bad: Forces layout on each iteration
for (let i = 0; i < boxes.length; i++) {
  const width = box.offsetWidth;   // reads (triggers layout)
  box.style.width = (width + 10) + 'px';  // writes
}
// ✅ Good: Batch reads, then batch writes
const widths = boxes.map(b => b.offsetWidth); // reads
boxes.forEach((b, i) => b.style.width = (widths[i] + 10) + 'px'); // writes

优化

  • 先读取布局属性,然后写入
  • 使用 transformopacity 进行动画(仅限合成器)
  • 避免复杂的 CSS 选择器在回流时触发选择器匹配
  • 使用 contain: layout style paint 隔离子树

第五阶段:油漆

浏览器将像素填充到图层中——文本、颜色、图像、边框、阴影。这是昂贵的,因为它涉及光栅化。单独的合成器层上的元素可以独立绘制。

油漆触发器

  • 更改为 colorbackground-colorvisibilityoutline
  • 添加阴影或文字装饰

第六阶段:复合

浏览器将绘制的图层合并到 GPU 上的最终帧中。相对于布局和绘制来说,合成成本较低。关键是尽量减少布局和绘制工作,以便大多数更改只需要合成。

仅限合成器的属性

物业触发器布局触发油漆仅合成器
占位符_0没有没有是的
占位符_0没有没有是的
占位符_0是的是的没有
占位符_0是的是的没有

阻塞资源与非阻塞资源

资源默认行为优化
CSS (<link>)渲染阻塞内联关键,延迟非关键
JS <script>解析器阻塞 (DOM)使用 asyncdefer
JS defer非阻塞,在 HTML 解析后执行订单已保留
JS async非阻塞,下载时执行无订单保证
<!-- ✅ Best practices -->
<script async src="analytics.js"></script>
<script defer src="app.js"></script>
<link rel="stylesheet" href="critical.css" />
<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'" />

衡量 CRP 绩效

Lighthouse 提供针对 CRP 的审计:

  • 消除渲染阻塞资源 — 识别阻塞 CSS/JS
  • 推迟屏幕外图像 — 减少绘画区域
  • 最小化主线程工作 - 识别长任务
  • 减少 JavaScript 执行时间 — 有助于解析器阻塞脚本

运行:npx lighthouse https://example.com --preset=desktop


结论

优化关键渲染路径需要了解 DOM/CSSOM 构造、渲染树形成、布局、绘制和合成的顺序性质。关键策略包括内联关键 CSS、对脚本使用 async/defer、通过批量 DOM 读/写避免布局抖动,以及优先使用仅限合成器的动画属性。定期 Lighthouse 审核有助于识别 CRP 瓶颈并指导持续改进。