浏览器的渲染原理
来总结一下最近理解的浏览器渲染原理和流程
首先浏览器是多进程的,分为渲染进程、插件进程、主进程、网络进程以及GPU进程
而我们打包出来的js html css文件,经过浏览器的渲染进程,就会展示出看到的页面。下面主要来了解一下浏览器的渲染进程
整个渲染流程分为一下几个阶段:
DOM构建、CSSOM构建、布局、分层、绘制、分块、光栅化、绘制
DOM构建
解析HTML转为DOM树。解析时,会把每个HTML标签解析成文档对象,再把每个文档对象用树形结构链接起来,最后把所有的文旦对象挂在document上,就形成了DOM树
需要注意的是,在解析HTML的时候,通常会有我们定义的link和script,解析过程中如果遇到css就解析css,遇到js解析js。所以为了提高解析效率,浏览器在解析前回启动一个预解析的线程,率先下载HTML中的外部引用文件和JS文件
如果在解析过程中遇到link文件还没有下载解析好,则放入预解析进程中解析,主线程继续HTML,不会被css阻塞;
如果主线程解析到script文件,则会挂起HTML解析,等待js解析完,这是因为js执行过程中可能会修改当前的DOM树,因此js会阻塞HTML的渲染进程
CSSOM构建
浏览器在构建DOM树的同时,会加载样式文件,同步进行CSSOM构建,CSSOM树主要是描述选择器之间的层级关系,也包括样式值
渲染树构建
渲染树是对DOM树和CSSOM树的结合,因为CSSOM树与DOM树并不是一一对应的,因为DOM树可能存在不展示的元素,因此需要进行DOM树遍历和CSSOM树查找。
遍历整个DOM树,生成一个渲染树,对于不需要展示的元素(display: none)则不会出现在渲染树中,再从CSSOM树里后序遍历查找样式,如果有多个样式命中一个节点,根据样式优先级挂载渲染树。
布局
至此以及有了渲染树和样式信息。遍历渲染树的每个节点,计算每个节点的几何信息,比如宽高位置等,将元素间的嵌套关系以盒模型的实行写入文档流,和模型在布局中会计算元素的确切位置和大小,将相应的信息协会渲染树上,生成布局渲染树。同时每个盒子携带样式信息,为后续绘制提供基础
分层
为了提升每一帧的渲染效率和复杂效果,主线程通过分层的方法,生成对应的图层树。之后某个图层有更改直接修改对应图层的样式,而不用重新构建CSSOM。
以hao123页面为例,可以看到分层效果
将一个页面分解成多个图层的操作就称之为分层,将这些图层合并到一层的操作就是合成。
通常情况,每个节点都包含一个图层,如果没有对应则属于父节点的图层。那怎么创建图层,可以通过以下方式:
- 背景边框
- z-index 负值 0 正值的定位元素
- 块级盒
- overflow
绘制
完成分层树之后,主线程就会为每个图层单独生产绘制指令,这些指令就形成了一个待绘制的列表,主线程将每个图层的绘制列表交给合成线程,剩余工作将由合成线程完成。如图所示
分块
合成线程拿到绘制列表后,首先会从线程池中拿去多个线程,进行图层的分块。
光栅化
完成分块之后,合成线程会将信息交给GPU进程,GPU则会开启多个线程快速进行光栅化,光栅化就是将所有的图块变成位图,它优先处理靠近视口附近的图块。
所谓的光栅化就是将绘制列表中的指令生成图片
绘制
至此所有图块都被光栅化。合成线程拿到光栅化信息后会生成指引(quad)指令,quad指令会包含每个位图的展示位置,旋转变形等。之后合成线程会将quad交给GPU进程,有GPU进程生产系统调用,交给GPU硬件,最终完成了屏幕成像。