浏览器是怎么渲染的?
浏览器工作大致流程
- 构建 DOM 树
- 预加载
- 构建 CSSOM 树
- Rendering Tree
- 布局( Layout )
- Paintting
- Compositing
- Interactivity
构建DOM树
处理 HTML 标记并构造 DOM 树,浏览器会遵守一套步骤将 HTML 文件转换为 DOM 树
预加载
浏览器构建 DOM 树时,这个过程占用了主线程。当这种情况发生时,Preload scanner将解析可用的内容并请求高优先级资源,如 CSS、JavaScript 和 web 字体。
它将在后台检索资源,以便在主 HTML 解析器到达请求的资源时,可能资源已经在运行,或者已经被下载。
当 JavaScript 解析和执行顺序不重要时,可以添加 async 属性或 defer 属性。
构建 CSSOM 树
DOM会捕获页面的内容,但浏览器还需要知道页面如何展示,所以需要构建CSSOM。
CSS 对象模型和 DOM 是相似的。DOM 和 CSSOM 是两棵树。它们是独立的数据结构。浏览器将 CSS 规则转换为可以理解和使用的样式映射。浏览器遍历 CSS 中的每个规则集,根据 CSS 选择器创建具有父、子和兄弟关系的节点树。
Style Rendering Tree
将 DOM 和 CSSOM 组合成一个 Render 树,计算样式树或渲染树从 DOM 树 的根开始构建,遍历每个可见节点。
布局 Layout
布局阶段需要完成两个任务:创建布局树和布局计算
通过遍历 DOM 树 创建渲染树 LayoutTree,通过计算 渲染树 上每个节点的样式,就能得出来每个元素所占空间的大小和位置。当有了所有元素的大小和位置后,就可以在浏览器的页面区域里去绘制元素的边框。
布局(Layout) 阶段会依次遍历 DOM树 的每一个节点,计算每个节点的几何信息。例如节点的宽度
大部分时候,DOM 树 和 节点树 并非是一一对应的。例如 display: none 的节点没有布局信息,那么也不会创建对应的 LayoutTree。
reflow(回流、重排)
回流是对页面的任何部分或整个文档的任何后续大小和位置的确定。
第一次确定节点的大小和位置称为布局(Layout)。随后对节点大小和位置的重新计算称为回流(reflow)。
当进行了会影响布局树的操作后,需要重新计算布局树,会引发 layout
例如
- 页面首次渲染;
- 浏览器窗口大小发生变化;
- 元素的内容发生变化;
- 元素的尺寸或者位置发生变化;
- 元素的字体大小发生变化;
- 激活CSS伪类;
- 查询某些属性或者调用某些方法;
- 添加或者删除可见的DOM元素。
repaint(重绘)
当对 DOM 的修改导致了样式的变化、但未影响其几何属性(比如修改颜色、背景色)时,浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式(会跳过重排环节),这个过程叫做 重绘。简单来说,重绘 是由对元素绘制属性的修改引发的
由于元素的布局信息也属于可见样式,所以 reflow 一定会引起 repaint
例如
- color、background 相关属性:background-color、background-image 等;
- outline 相关属性:outline-color、outline-width 、text-decoration;
- border-radius、visibility、box-shadow。
分层 Layer
主线程会使用一套复杂的策略对整个布局树中进行分层
滚动条、堆叠上下文、transform、opacity 等样式都会对分层结果有或多或少影响,也可以通过 will-change 属性更大程度的影响分层结果
Paintting
将各个节点绘制到屏幕上,绘制可以将布局树中的元素分解为多个层。将内容提升到 GPU 上的层(而不是 CPU 上的主线程)可以提高绘制和重新绘制性能。
Compositing
当文档的各个部分以不同的层绘制,相互重叠时,必须进行合成,以确保它们以正确的顺序绘制到屏幕上,并正确显示内容。
参考文章:
