当前位置: 首页 > news >正文

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

浏览器渲染就是把网页代码(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><div>Hello</div>
</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 -> blockReflow + 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、CSSHTML 解析、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) 提升首屏渲染速度。

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

http://www.lryc.cn/news/610842.html

相关文章:

  • ArrayList 深度剖析:从底层原理到性能优化的实战指南
  • MySQL索引底层原理与性能优化实践
  • 力扣:2246. 相邻字符不同的最长路径
  • 解析图像几何变换:从欧式到仿射再到透视
  • 从达梦到 StarRocks:国产数据库实时入仓实践
  • Python高级编程与实践:Python装饰器深入解析与应用
  • 使用 BAML 模糊解析改进 LangChain 知识图谱提取:成功率从25%提升到99%
  • 力扣刷题日常(15-16)
  • 【Electron】electron-vite中基于electron-builder与electron-updater实现程序远程自动更新,附源码
  • 国产大模型平替方案:Spring Boot通义千问API集成指南
  • 2025 年半导体用铜前驱体市场规模有多大?全景调研及投资前景分析
  • 接口测试用例书写规范
  • 基于 FFmpeg 与 V4L2 的多路摄像头视频采集,图像处理处理与 RTMP 推流项目(开源)
  • 【教育教学】人才培养方案制定
  • Linux内核C语言代码规范
  • MySQL内外连接详解
  • Python 基础语法(二):流程控制语句详解
  • 【Qt开发】常用控件(一)
  • 嵌入式硬件中运放的基本控制原理
  • 选佳沐信,智享便捷,乐在其中
  • LeetCode——2683. 相邻值的按位异或
  • 下架的软件又复活了,低调使用!
  • HFSS许可审计与分析
  • 用 Python 批量处理 Excel:从重复值清洗到数据可视化
  • Go语言实战案例:使用context控制协程取消
  • 【工程化】tree-shaking 的作用以及配置
  • 小杰数据结构——题库——拂衣便欲沧海去,但许明月随吾身
  • EP02:【DL 第二弹】张量的索引、分片、合并以及维度调整
  • WWDC 25 极地冰原撸码危机:InlineArray 与 Span 的绝地反击
  • 基于MCP的智能客服系统:知识库与工单系统深度集成