浏览器渲染 首屏优化 性能优化

浏览器渲染就是把网页代码(HTML、CSS、JS、图片等)变成用户眼中看到的"可视页面"的过程

复制代码
HTML 文本
   ↓
1. 解析 HTML,构建 DOM 树
   ↓
2. 解析 CSS,构建 CSSOM 树
   ↓
3. 合并 DOM + CSSOM,生成 Render Tree(渲染树)
   ↓
4. Layout(布局计算)
   ↓
5. Paint(像素填充)
   ↓
6. Composite(图层合成)

1. 构建 DOM 树(Document Object Model)

  • 浏览器主线程解析 HTML

  • 每一个标签节点都会被转换为一个 JS 对象(DOM 节点)

  • 忽略 script、style 标签的 CSS(先不执行 JS 和样式

    <body>
    Hello
    </body>

会变成:

复制代码
Document
└── body
    └── div

2. 构建 CSSOM 树(CSS Object Model)

  • 浏览器解析

    div {
    color: red;
    }
    CSSOM 是类似这样的结构:
    StyleSheet
    └── Rule: div { color: red; }

生成渲染树(Render Tree)

  • DOM + CSSOM 合并,生成一棵 "Render Tree"
  • 不包括 display: none 的元素
  • 每个可见节点会变成一个 "渲染对象"(RenderObject)
  • 🧠 渲染树是"只包含可视化元素"的 DOM + CSS 组合体

4. Layout(布局阶段

复制代码
也叫 Reflow(回流)

计算每个渲染对象的具体位置、大小(几何信息)

涉及布局模型(Block、Flex、Grid等)

输出的是每个元素的:坐标、宽高、边距、盒模型等信息

5. Paint(绘制阶段)

复制代码
也叫 重绘(Repaint)

把每个节点的视觉样式(颜色、文字、边框、阴影等)画到屏幕的图层中

形成一个或多个位图(Bitmap)

注意:绘制是按图层进行的

6. Composite(合成阶段)

复制代码
多个图层合成一张页面最终画面

使用 GPU 加速合成(硬件加速)

对于复杂动画、transform、position: fixed 等会被放入独立图层

示意图(流程图)

复制代码
HTML + CSS + JS
    ↓
【DOM】 ← HTML Parser
【CSSOM】 ← CSS Parser
    ↓
【Render Tree】
    ↓
Layout(计算位置)
    ↓
Paint(绘制位图)
    ↓
Composite(合成图层)
    ↓
【用户可见页面】

1. 网络请求(下载 HTML/CSS/JS/图片)
2. 构建 DOM 树(HTML → DOM)
3. 构建 CSSOM 树(CSS → CSSOM)
4. 构建 Render Tree(DOM + CSSOM)
5. 布局(Layout / Reflow)
6. 绘制(Paint)
7. 合成层 & 合成(Compositing)
8. 显示到屏幕

渲染相关的性能点

操作类型 影响
改变 DOM 结构 触发 Reflow + Repaint
改变样式(颜色) 触发 Repaint
改变 layout 样式(宽高、位置) 触发 Reflow + Repaint
改变 transform、opacity 不触发 Reflow,仅触发 GPU 合成

Reflow vs Repaint

名称 含义 性能影响
Reflow 布局计算(改变大小/位置) 🟥 非常消耗
Repaint 样式重绘(颜色、字体变化) 🟨 一般消耗
复制代码
div.style.width = '100px';  // Reflow + Repaint
div.style.backgroundColor = 'red';  // 只 Repaint

浏览器帧率与渲染时机(重要)

浏览器渲染遵循 刷新率 60Hz(16.6ms 一帧):

JS 主线程 + 渲染引擎 合作完成每一帧

requestAnimationFrame

用于让代码在"下一帧绘制前"运行

复制代码
requestAnimationFrame(() => {
  // 更新 DOM 的操作,保证在下一帧渲染前完成
});

一个复杂变化时的例子(动图)

复制代码
div.style.transform = 'translateX(100px)';
// 👉 创建新图层 → GPU 加速 → 合成阶段处理
但如果你这样:
div.style.left = '100px';
// 👉 会触发回流 → 性能下降

总结一句话:

浏览器渲染过程是:DOM + CSSOM → Render Tree → Layout → Paint → Composite → 屏幕呈现。其中任何一步变化都会影响页面性能与流畅度。

什么是渲染管线(Rendering Pipeline)?

  • 渲染管线是浏览器从接收网页代码(HTML/CSS/JS)到最终绘制在屏幕上的整个技术过程的专业称呼。它是浏览器内部的核心流程。

渲染管线的六大步骤

复制代码
HTML/CSS/JS
  ↓
1. 构建 DOM 树
2. 构建 CSSOM 树
3. 构建渲染树(Render Tree)
4. 布局(Layout / Reflow)
5. 绘制(Paint / Repaint)
6. 合成(Composite)
  ↓
GPU 将图像显示在屏幕

渲染管线图示(直观理解)

复制代码
HTML/CSS
  ↓        JavaScript可能修改DOM
[DOM] + [CSSOM]
  ↓
[Render Tree]
  ↓
[Layout / 回流]
  ↓
[Paint / 重绘]
  ↓
[Composite / 合成]
  ↓
[屏幕显示]

触发渲染管线的时机

操作 触发阶段
修改 DOM 结构 Reflow + Paint + Composite
修改宽高/位置/字体等 Layout 属性 Reflow + Paint + Composite
修改颜色、背景等 Paint 属性 Paint + Composite
修改 transform, opacity 只触发 Composite(性能好)

实际应用:开发者如何影响渲染管线?

技术/操作 渲染行为 是否性能友好
transform: translate() 只触发 Composite ✅ 非常高效
display: none -> block Reflow + Paint ❌ 慎用
background-color 改变 Paint 🟡 一般
width 改变 Reflow + Paint ❌ 重计算布局
使用 will-change 优化动画 创建独立层,避免 Paint ✅ 高效

渲染管线 VS 事件循环?

渲染管线 事件循环
负责页面"如何画出来" 负责 JS 任务"如何调度执行"
处理 DOM → 屏幕的全过程 处理 JS 同步 + 异步任务执行
涉及 GPU、合成、像素渲染 涉及调用栈、任务队列、回调调度
60FPS 性能优化关注点 异步控制流程优化关注点

哪些因素会影响首屏加载和性能

阻塞渲染的资源

2. JavaScript 执行太久

复制代码
如果主线程执行了很长时间的 JS(例如循环、大量计算),那么:

会阻塞 DOM 更新

阻塞页面响应(用户点击没有反应)

甚至阻塞定时器(比如 setTimeout 会延迟)

频繁的 Layout / Repaint / Reflow

复制代码
CSS 操作或 DOM 操作不当会导致:

多次回流(Reflow)

多次重绘(Repaint)


for (let i = 0; i < 1000; i++) {
  element.style.marginLeft = i + 'px';
}
优化建议:
  • 使用 class 一次性改变样式

  • 使用 documentFragment 批量操作 DOM

  • 使用 will-change 提前告诉浏览器优化

首屏加载优化点总结

优化点 影响阶段 说明
压缩/合并 JS、CSS HTML 解析、CSSOM 构建 减少请求数,提升速度
JS 加 deferasync 避免阻塞渲染 defer 等待 DOM 构建后执行;async 并行加载
图片懒加载 Paint 阶段 减少非首屏图片加载
CSS 放头部、JS 放尾部 HTML 解析 避免阻塞
使用 Skeleton 骨架屏 Paint 阶段 改善用户体验,看起来加载更快
使用 SSR 或 CSR + 缓存 全局 服务端渲染 + 缓存提升首屏速度

重要概念

  • DOM 树:HTML 标签构成的树结构。

  • CSSOM 树:CSS 规则构成的样式树。

  • Render Tree:渲染树,仅包含可见节点及其样式。

  • 回流(Reflow):重新计算布局(大小、位置)。

  • 重绘(Repaint):节点视觉变化(颜色、背景等)但不改变布局。

  • 合成(Composite):合成多图层,最终绘制到屏幕。

什么会触发回流与重绘

操作 触发回流 触发重绘
改变元素大小、位置(width, height, top, left)
添加或删除可见元素
改变字体大小、边距
改变颜色、背景色
visibility: hidden → visible

性能优化建议

  • 减少回流:避免频繁修改影响布局的属性。

  • 批量修改 DOM:用 DocumentFragment 或虚拟 DOM 减少操作次数。

  • CSS 动画优先用 transform 和 opacity:只触发合成,性能好。

  • 用 requestAnimationFrame 控制动画帧率。

  • 合理使用 will-change:提前告诉浏览器哪些元素会变,提前创建合成层。

  • 避免阻塞主线程的长同步任务:避免页面卡顿。

首屏加载优化重点

  • 减少阻塞资源:CSS 放头部,JS 放尾部,使用 defer 或 async。

  • 避免大 JS 任务阻塞主线程。

  • 图片懒加载,减少初始绘制压力。

  • 服务端渲染(SSR) 提升首屏渲染速度。

  • 骨架屏 提高用户感知速度

相关推荐
歪歪1003 小时前
HTML 如何转 Markdown
开发语言·chrome·python·程序人生·html
大熊学员7 小时前
HTML与JavaScript的羁绊
前端·css·html
鲸渔9 小时前
CSS高频属性速查指南
前端·css·css3
MrSkye11 小时前
🔥前端小白到高手之路必学:渲染过程与回流重绘详解🔥
前端·面试·浏览器
Java&Develop12 小时前
用html写一个类似于postman可以发送请求
前端·html·postman
然我13 小时前
iPad 体验为何让人上瘾?关键藏在这个 Html5 API 里!
前端·面试·html
泯泷13 小时前
Tiptap 深度教程 (一):理解 Tiptap 的设计哲学与核心架构
前端·前端框架·html
前端老鹰16 小时前
CSS overscroll-behavior:解决滚动穿透的 “边界控制” 专家
前端·css·html
limnade17 小时前
Flask + HTML 项目开发思路
python·flask·html