浏览器渲染

  • 浏览器渲染已关闭评论
  • 33 次浏览
  • A+
所属分类:Web前端
摘要

浏览器渲染网页是一个复杂的过程,这个过程涉及关键渲染路径(CRP)。CRP 包含从获取 HTML、CSS 和 JavaScript 资源开始,到最终将像素呈现在屏幕上的一系列关键步骤,这些步骤包括解析 HTML、解析 CSS、布局以及绘制等多个环节,


关键渲染路径(CRP)

浏览器渲染网页是一个复杂的过程,这个过程涉及关键渲染路径(CRP)。CRP 包含从获取 HTML、CSS 和 JavaScript 资源开始,到最终将像素呈现在屏幕上的一系列关键步骤,这些步骤包括解析 HTML、解析 CSS、布局以及绘制等多个环节,

MDN上的描述

浏览器开始解析 HTML,将收到的数据转换为 DOM 树。当浏览器每次发现 DOM 树包含外部资源就会初始化其请求(无论是样式、脚本或者嵌入的图片引用)。有时这些请求会阻塞,意味着解析剩下的 HTML 会被终止,直到前面这些重要的资源得到处理。浏览器接着解析 HTML,发送请求并构造 DOM,直到 HTML 的文件结尾,此时就会开始构造 CSSOM。等到 DOM 和 CSSOM 完成之后,浏览器构造渲染树,计算所有可见内容的样式。一旦渲染树完成,布局就会开始,定义所有渲染树元素的位置和大小。在布局完成后,页面被渲染完成(被绘制到屏幕上)。

浏览器渲染流程

得到HTML

浏览器接收到HTTP响应的数据包,这些数据包包含HTML,CSS,JavaScript以及可能的图片和其他资源。

解析HTML

意义:

  • 由于字符串难以进行操作,浏览器首先会将 HTML 字符串解析成 DOM 树和 CSSOM 树这种容易操作的对象结构,也提供了 JS 操作这两颗树的能力
  • 构建 CSSOM 树主要是使得浏览器能够更高效地理解和处理样式之间的关系。

实现:

  • 构建 DOM 树:浏览器首先会解析 HTML 文档,构建一个 DOM(文档对象模型)树。每个 HTML 元素都会成为树中的一个节点。
  • 构建 CSSOM 树:DOM 树构建完成一部分后开始构建 CSSOM 树,当浏览器开始解析 HTML 时,它也会同时发现并请求 CSS 资源。一旦 CSS 文件开始被接收并解析,或者当遇到内联 CSS 时,浏览器就会开始构建 CSSOM 树。

解析CSS(样式计算)

意义:

  • 样式控制和动态更新:
    • JavaScript 可以通过操作 CSSOM 树来动态修改元素的样式
  • 渲染树合成基础:
    • CSS 计算得到的每个元素的样式信息是构建渲染树的重要基础。

过程:

  • 样式收集和处理:
    • 浏览器首先收集来自不同来源的样式信息,包括内联样式<style>标签内的样式以及外部 CSS 文件。
    • 对于<style>标签内的样式和外部 CSS 文件,浏览器会按照它们在 HTML 文档中的加载顺序进行解析
  • 标记化和语法分析
    • 对收集到的 CSS 样式内容进行标记化,将其分解成一个个的标记;
  • 构建 CSSOM 树
  • 浏览器根据 CSS 的层叠规则来计算每个元素最终的样式
    • 依次为树中的每个节点计算出它最终的样式,称之为 Computed Style

注意:CSS 是渲染阻塞的:浏览器会阻塞页面渲染直到它接收和执行了所有的 CSS。CSS 是渲染阻塞是因为规则可以被覆盖,所以直至 CSSOM 构建完成之前,内容都不能被渲染。

布局

意义:

  • 渲染树的构建是将 DOM 树和 CSSOM 树结合的过程,
  • 布局取决于屏幕的尺寸。布局这个步骤决定了在哪里和如何在页面上放置元素,决定了每个元素的宽和高,以及他们之间的相关性。

过程:

  • 生成布局树(渲染树)
    • 浏览器检查每个节点,从 DOM 树的根节点开始,并且决定哪些 CSS 规则被添加。渲染树只包含了可见内容。 在DOM树上不可见的元素,最后都不会出现在布局树上。
  • 计算布局(回流):
    • 一旦渲染树构建完成,浏览器会计算每个节点的几何信息,包括位置和大小,这个过程称为布局(或回流)。

分层(绘制)

意义:

  • 分层的好处在于,将来某一个层改变后,仅会对该层进行后续处理,只需要更新特定的层,而不是整个页面,减少了重绘的范围

过程:

  • 对渲染树进行分层:
    • 渲染主线程会使用一套复杂的策略对整个布局树(渲染树)进行分层。例如,具有 3D 变换、视频元素或者使用了硬件加速的元素通常会被单独分层。
  • 生成绘制列表:
    • 渲染主线程会根据计算好的样式和布局信息,为每个图层单独生成绘制指令集,这些绘制指令会告诉浏览器的图形处理单元(GPU)如何将元素绘制到屏幕上。

分块

意义:

  • 分块就是将页面划分成多个小的矩形区域(块),如果一次性处理整个页面的绘制,会消耗大量的系统资源并且可能导致性能问题。分块就是将页面划分减少绘制时的消耗

过程:

  • 浏览器(合成线程)对每个图层进行分块,根据布局信息来确定哪些块是当前可见的或者即将可见的(考虑到滚动等情况)。对于每个块,会独立地进行绘制操作。

光栅化

意义:

  • 光栅化就是将矢量图形(如由 HTML 和 CSS 定义的各种页面元素形状)转换为位图(由像素组成的图像)的过程,这是为了让图形能够在以像素为基础的显示器上正确显示

过程:

  • 确定光栅化区域:
    • 浏览器首先需要确定哪些区域的网页元素需要进行光栅化。这通常是基于布局和分层信息来判断的。
  • 矢量图形转换为位图:
    • 对于需要光栅化的元素,浏览器将其矢量图形表示(如根据 CSS 样式定义的形状、文本的字体轮廓等)按照一定的算法转换为位图。
  • 像素数据处理和优化:

合成

意义:

  • 当文档的各个部分以不同的层绘制,相互重叠时,必须进行合成,以确保它们以正确的顺序绘制到屏幕上,并正确显示内容。
  • 实现高效更新和动画效果:
    • 某些元素的变化可能只涉及到特定的层,通过合成,浏览器可以只更新受影响的层。

实现:

  • 生成合成指令
    • 合成线程根据每个层的信息(包括层的位置、大小、透明度等)以及它们之间的关系,生成一系列的合成指令。这些指令类似于一个 “蓝图”,告诉浏览器如何将各个层的内容进行组合和绘制。
  • 提交给 GPU 进行处理:
    • 合成线程将生成的合成指令提交给 GPU 进程。GPU 进程接收到指令后,会根据指令中的信息进行具体的图形处理操作。
  • 完成屏幕成像:
    • GPU 完成合成操作后,会产生系统调用,将合成后的图像数据提交给 GPU 硬件,最终完成在屏幕上的成像显示。

各个步骤输入输出

每个阶段都有明确的输入输出,上一个阶段的输出会成为下一个阶段的输入。

输入 输出
解析 HTML 与 CSS HTML 文档内容(字节) DOM 树
样式计算 DOM 树 DOM 树和 CSSOM 树
布局 DOM 树和 CSSOM 树 渲染树
分层 渲染树 分层后的结构
分块 分层后的结构 矢量图形信息
光栅化 矢量图形信息 每个块的位图(像素矩阵)
合成 位图数据 最终合成后的图像数据