浏览器渲染流程初探

479 阅读4分钟

image.png

浏览器渲染的流程

浏览器渲染是指浏览器将 HTML、CSS 和 JavaScript 等前端资源转换为可视化的页面的过程。浏览器渲染的过程可以分为以下几个步骤:

  1. 解析 HTML,构建 DOM 树

当浏览器接收到 HTML 代码时,它会逐行解析代码,并创建一个由 DOM 元素和节点组成的树形结构,即 DOM 树。DOM 树中的每个元素都是一个节点,它们的关系构成了一棵树状结构。在构建 DOM 树的过程中,浏览器会执行以下操作:

  • 根据 HTML 代码中的标签和属性等信息,创建相应的 DOM 元素。
  • 将 DOM 元素按照其在 HTML 代码中的嵌套关系,构建出一个树形结构。

image.png

若解析过程中,读取到CSS或JS,停止解析(阻塞),转而解析CSS或执行JS

为什么要将CSS写到页面的开头,而JS写到页面的最后?

将CSS写到页面开头,是为了让浏览器尽快读取并解析样式,避免给用户看到丑陋的页面,也是为了避免页面闪烁

将JS代码写到最后,是为了让浏览器尽快呈现页面给用户,然后再执行JS完成交互功能

  1. 解析 CSS,构建 CSSOM 树

在构建好 DOM 树后,浏览器会解析 CSS 样式,将 CSS 样式表转换为 CSSOM 树。CSSOM 树和 DOM 树很类似,但它是由 CSS 规则组成的树形结构。在构建 CSSOM 树的过程中,浏览器会执行以下操作:

  • 根据 CSS 选择器和样式声明,创建相应的 CSS 规则。
  • 将 CSS 规则按照其在 CSS 样式表中的顺序,构建出一个树形结构。
  1. 合并 DOM 树和 CSSOM 树,生成渲染树

将 DOM 树和 CSSOM 树合并,生成渲染树。渲染树只包含需要显示在页面上的节点和相关样式信息。例如,一些不可见的元素(如 head 和 script 标签)以及不需要显示的元素(如 display:none)将被忽略。在构建渲染树的过程中,浏览器会执行以下操作:

  • 遍历 DOM 树上的每个节点。
  • 为每个节点匹配相应的 CSS 规则,生成渲染树节点。
  • 合并渲染树上的节点,形成最终的渲染树。

image.png

当DOM树完全生成好后,会触发DOMContentLoaded事件

document.addEventListener("DOMContentLoaded", function() {
  console.log("DOM树已全部生成完毕");
});

当页面中的所有外部资源全部加载完毕后,会触发load事件

window.onload = function(){
  console.log("所有资源已加载完成");
}

load事件也可以针对单个外部资源使用,资源加载完成后触发

  1. 计算渲染树节点的布局信息

渲染树中的每个节点都有一个位置和大小。浏览器通过计算渲染树节点的布局信息来确定它们的位置和大小。在计算布局信息的过程中,浏览器会执行以下操作:

  • 遍历渲染树上的每个节点。
  • 根据节点的样式信息,计算它的位置和大小。
  • 计算子节点的位置和大小。

这个步骤会在页面之后的运行过程中不断的重复,下面的JS操作均会导致reflow

  • 获取元素的尺寸和位置
  • 直接或间接改变元素的尺寸和位置

reflow非常耗时,浏览器为了提升性能,对JS中连续导致reflow的代码,把reflow的时间点延迟到结束后进行,但在此过程中,如果遇到了获取尺寸和位置的代码,浏览器会迫不得已立即reflow

dom.style.width = '100px'
dom.style.height = '200px'
dom.style.left = '10px'
dom.style.top = '10px'

image-20211222145016258

dom.style.width = '100px'
dom.style.height = '200px'
dom.clientHeight; // 读取高度,导致强行reflow
dom.style.left = '10px'
dom.style.top = '10px'

读取 CSS 属性的操作本身并不会触发回流(reflow),但如果读取的属性需要根据页面布局计算,就可能会触发回流。比如,如果要读取元素的宽度属性(例如,offsetWidthclientWidth),浏览器就必须计算元素的边框、内边距和内容区域的宽度,并考虑元素是否应该被滚动等因素。如果元素的布局属性已经发生了变化,比如改变了宽度或高度,那么浏览器就必须重新计算元素的宽度,这就会触发回流。

比如,如果要读取元素的宽度属性(例如,offsetWidthclientWidth),浏览器就必须计算元素的边框、内边距和内容区域的宽度,并考虑元素是否应该被滚动等因素。如果元素的布局属性已经发生了变化,比如改变了宽度或高度,那么浏览器就必须重新计算元素的宽度,这就会触发回流。

  1. 将渲染树绘制到屏幕上

合成是将绘制的结果按照合适的顺序合成到屏幕上,以显示出最终的效果。浏览器采用多层合成的方式,将不同的图层分别绘制,最后将它们合成到一起,以提高性能和用户体验。