Skip to content
  • 目标:
  • 亲眼看到一次页面渲染经历了:JS → Layout → Paint → Composite

一、准备一个“必出效果”的 Demo

先建一个最简单的 HTML(本地打开即可):

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <title>Render Demo</title>
  <style>
    .box {
      width: 100px;
      height: 100px;
      background: red;
      margin: 20px;
      transition: transform 0.5s;
    }
  </style>
</head>
<body>
  <button id="btn">Move</button>
  <div class="box" id="box"></div>

  <script>
    const box = document.getElementById('box')
    document.getElementById('btn').onclick = () => {
      // 强制触发 layout
      console.log(box.offsetWidth)

      // 只触发 composite
      box.style.transform = 'translateX(200px)'
    }
  </script>
</body>
</html>

这个例子故意包含

  • 一次 强制回流
  • 一次 只走合成层的动画

二、打开 Performance 面板(核心工具)

  1. 打开页面

  2. F12 / Cmd + Option + I

  3. 切到 Performance

  4. 勾选:

    • ✅ Screenshots
    • ✅ Web Vitals(可选)

三、录制一次渲染过程

1️⃣ 点击 Record(●)

2️⃣ 点击页面里的 Move

3️⃣ 等动画结束

4️⃣ 点击 Stop(■)

你现在看到的是浏览器最真实的内部执行轨迹

四、读懂 Performance 时间线(重点)

1️⃣ 总览区域(顶部)

你会看到几条颜色条:

颜色含义
🟨 黄色JS 执行
🟪 紫色Style / Layout
🟩 绿色Paint
🟦 蓝色Composite

📌 目标状态:动画阶段几乎只有 🟦

2️⃣ Main 线程(最重要)

展开 Main

Task
 ├── Event: click
 │    ├── Function Call
 │    │    ├── offsetWidth   ← 强制回流
 │    │    ├── set style
 │    ├── Layout
 │    ├── Paint
 └── Composite Layers

你会清楚看到:

👉 读 offsetWidth → 浏览器被迫执行 Layout → 后续 transform 不再触发布局

🔥 关键知识点(非常重要)

为什么 offsetWidth 会触发 Layout?

因为浏览器内部是惰性计算布局的

  • 改样式:先记账
  • 读布局信息:必须算一次

这就是 Layout Thrashing 的根源

五、验证:transform 是否真的没有回流?

打开 Rendering 面板

  1. DevTools → More toolsRendering

  2. 勾选:

    • ✅ Paint flashing
    • ✅ Layer borders

再点一次按钮

你会看到:

  • 盒子 闪蓝色边框(合成层)
  • 没有绿色闪烁(没有重绘)

✔️ 证明只发生了 Composite

六、对比实验(非常关键)

把 JS 改成:

js
box.style.left = '200px'

并加:

css
.box {
  position: relative;
}

重新录制 Performance。

你会看到:

  • 每一帧都有:

    • Layout
    • Paint
  • FPS 明显下降

👉 这就是为什么动画要用 transform

七、用 FPS Meter 看流畅度

  1. Rendering 面板
  2. 勾选 FPS meter

对比:

  • left 动画:FPS 波动大
  • transform:稳定 60

八、总结

  • 一次完整的浏览器渲染流程是:
  • DOM 和 CSSOM 构建完成后生成 Render Tree,
  • 然后进行 Layout 计算几何信息,
  • 接着 Paint 绘制像素,
  • 最后由 GPU 进行 Composite 合成。
  • 在 DevTools 的 Performance 面板中,可以看到
  • JS、Layout、Paint、Composite 的执行时间,
  • 使用 transform 和 opacity 可以跳过 Layout 和 Paint,只走合成层,从而获得更好的性能。