浏览器渲染的核心流程及详细解析(2025.6月最新)

浏览器的渲染过程是将 HTML、CSS 和 JavaScript 转换成用户可见的网页的过程。这个过程涉及多个关键步骤,从解析文档到最终绘制像素到屏幕上。下面详细介绍浏览器的渲染流程,并结合具体示例说明。


1. 浏览器渲染的核心流程

浏览器渲染主要分为以下几个阶段:

  1. 解析 HTML → 构建 DOM 树
  2. 解析 CSS → 构建 CSSOM 树
  3. 合并 DOM 和 CSSOM → 生成 Render Tree(渲染树)
  4. 计算布局(Layout / Reflow)
  5. 绘制(Paint)
  6. 合成(Composite) (现代浏览器优化)

2. 详细步骤解析

(1)解析 HTML → 构建 DOM 树

  • 输入:HTML 文档(字符串)

  • 输出:DOM(Document Object Model)树,表示网页的结构

  • 过程

    • 浏览器逐行读取 HTML,解析标签并生成节点。
    • 遇到 <script><link> 等外部资源时会阻塞解析(除非标记 async/defer)。

示例

xml 复制代码
<!DOCTYPE html>
<html>
<head>
  <title>Demo</title>
</head>
<body>
  <h1>Hello World</h1>
  <p>This is a paragraph.</p>
</body>
</html>

DOM 树结构

  • html
    • head
    • title
    • "Demo"
    • body
    • h1
    • "Hello World"
    • p
    • "This is a paragraph."

(2)解析 CSS → 构建 CSSOM 树

  • 输入 :CSS 样式表(内联、外部、<style>

  • 输出:CSSOM(CSS Object Model)树,表示样式规则

  • 特点

    • CSS 解析是 层叠的!important、选择器优先级)。
    • CSS 解析会 阻塞渲染(Render Blocking)。

示例

css 复制代码
h1 { color: red; }
p { font-size: 16px; }

CSSOM 树结构

css 复制代码
- h1
  - color: red
- p
  - font-size: 16px

(3)合并 DOM + CSSOM → 生成 Render Tree

  • 输入:DOM + CSSOM

  • 输出 :Render Tree(仅包含 可见元素 ,如 display: none 的元素不会进入 Render Tree)

  • 关键点

    • 只包含 需要渲染的节点 (如 visibility: hidden 仍会占据空间,所以会进入 Render Tree)。
    • 伪元素(::before, ::after)也会被包含。

示例

假设 DOM 和 CSSOM 如上,Render Tree 结构:

less 复制代码
- body
  - h1 (color: red)
    - "Hello World"
  - p (font-size: 16px)
    - "This is a paragraph."

(4)计算布局(Layout / Reflow)

  • 作用 :计算每个元素在屏幕上的 精确位置和大小

  • 触发条件

    • 首次加载
    • 窗口大小变化(resize
    • 修改 DOM 或样式(如 widthmargin

示例

css 复制代码
p { width: 50%; margin: 10px; }

浏览器会计算:

  • p 的宽度 = 父容器宽度 × 50%
  • 外边距 margin: 10px

(5)绘制(Paint)

  • 作用 :将 Render Tree 转换成屏幕上的 像素

  • 过程

    • 遍历 Render Tree,调用底层图形 API(如 Skia in Chrome)绘制颜色、边框、文本等。
    • 可能涉及 分层绘制 (如 transform 会单独一层)。

示例

  • h1 被绘制为红色文本
  • p 被绘制为 16px 的黑色文本

(6)合成(Composite)

  • 作用:将不同图层(Layers)合并成最终画面

  • 优化手段

    • GPU 加速(transformopacity 等属性会触发 GPU 合成)
    • 减少重绘(Repaint)和回流(Reflow)

示例

css 复制代码
.box { transform: translateZ(0); } /* 强制 GPU 加速 */

3. 关键渲染路径优化

(1)减少阻塞

  • CSS

    • 使用 <link rel="stylesheet" media="print"> 避免非关键 CSS 阻塞渲染。
    • 内联关键 CSS(Critical CSS)。
  • JavaScript

    • 使用 asyncdefer 延迟脚本加载。

(2)减少回流(Reflow)和重绘(Repaint)

  • 避免频繁修改样式

    ini 复制代码
    // ❌ 糟糕:多次触发回流
    el.style.width = '100px';
    el.style.height = '200px';
    
    // ✅ 优化:使用 class 或 requestAnimationFrame
    el.classList.add('new-size');
  • 使用 transformopacity(只触发合成,不触发回流)。

(3)使用开发者工具分析

  • Chrome DevTools → Performance 面板:

    • 查看 Layout、Paint、Composite 耗时。
    • 检测强制同步布局(Forced Synchronous Layout)。

4. 完整示例

场景:动态添加列表项

ini 复制代码
<ul id="list"></ul>
<button onclick="addItems()">Add Items</button>
<script>
  function addItems() {
    const list = document.getElementById('list');
    // ❌ 糟糕:每次循环都触发回流
    for (let i = 0; i < 100; i++) {
      const li = document.createElement('li');
      li.textContent = `Item ${i}`;
      list.appendChild(li); // 触发 100 次回流
    }

    // ✅ 优化:使用 DocumentFragment 批量操作
    const fragment = document.createDocumentFragment();
    for (let i = 0; i < 100; i++) {
      const li = document.createElement('li');
      li.textContent = `Item ${i}`;
      fragment.appendChild(li);
    }
    list.appendChild(fragment); // 只触发 1 次回流
  }
</script>

5. 总结

阶段 关键点 优化建议
DOM 构建 解析 HTML → 生成 DOM 减少 DOM 深度,避免复杂嵌套
CSSOM 构建 解析 CSS → 生成 CSSOM 内联关键 CSS,异步加载非关键 CSS
Render Tree 合并 DOM + CSSOM 避免 display: none 滥用
Layout 计算元素位置/大小 避免强制同步布局
Paint 填充像素 减少复杂阴影/渐变
Composite 合并图层 使用 transform/opacity 优化

通过理解浏览器的渲染机制,可以更高效地优化网页性能,减少卡顿和加载时间。

相关推荐
又又呢6 分钟前
前端面试题总结——webpack篇
前端·webpack·node.js
dog shit1 小时前
web第十次课后作业--Mybatis的增删改查
android·前端·mybatis
我有一只臭臭1 小时前
el-tabs 切换时数据不更新的问题
前端·vue.js
七灵微1 小时前
【前端】工具链一本通
前端
Nueuis2 小时前
微信小程序前端面经
前端·微信小程序·小程序
_r0bin_4 小时前
前端面试准备-7
开发语言·前端·javascript·fetch·跨域·class
IT瘾君4 小时前
JavaWeb:前端工程化-Vue
前端·javascript·vue.js
potender5 小时前
前端框架Vue
前端·vue.js·前端框架
站在风口的猪11085 小时前
《前端面试题:CSS预处理器(Sass、Less等)》
前端·css·html·less·css3·sass·html5
程序员的世界你不懂6 小时前
(9)-Fiddler抓包-Fiddler如何设置捕获Https会话
前端·https·fiddler