对付很多前端开拓来说,平常做工紧张专注于业务开拓,对浏览器的渲染阶段可能不是很理解。实际上这个阶段很主要,理解浏览器的渲染过程,能让我们知道我们写的HTML、CSS、JS代码是如何被解析,并终极渲染成一个页面的,在页面性能优化的时候有相应的办理思路。
我们先来看一个问题:
HTML、CSS、JS文件在浏览器中是如何转化成页面的?
如果你回答不上来,那就往下看吧。
按照渲染的韶光顺序,渲染过程可以分为下面几个子阶段:构建DOM树、样式打算、布局阶段、分层、栅格化和合成显示。
下面详细看下每个阶段都做了哪些事情。
1. 构建DOM树HTML文档描述一个页面的构造,但是浏览器无法直接理解和利用HTML,以是须要通过HTML解析器将HTML转换成浏览器能够理解的构造——DOM树。
HTML文档中所有内容皆为节点,各节点之间有层级关系,彼此相连,构成DOM树。
构建过程:读取HTML文档的字节(Bytes),将字节转换成字符(Chars),依据字符确定标签(Tokens),将标签转换成节点(Nodes),以节点为基准构建DOM树。参考下图:
打开Chrome的开拓者工具,在掌握台输入 document 后回车,就能看到一个完全的DOM树构造,如下图所示:
在掌握台打印出来的DOM构造和HTML内容险些一样,但和HTML不同的是,DOM是保存在内存中的树状构造,可以通过JavaScript来查询或修正其内容。
2. 样式打算样式打算这个阶段,是为了打算出DOM节点中每个元素的表现样式。
2.1 解析CSSCSS样式可以通过下面三种办法引入:
通过link引用外部的CSS文件style 标签内的CSS元素的style属性内嵌的CSS和HTML一样,浏览器无法直接理解纯文本的CSS样式,须要通过CSS解析器将CSS解析成 styleSheets 构造,也便是我们常说的 CSSOM树。
styleSheets构造同样具备查询和修正功能:
document.styleSheets
属性值标准化看字面意思有点不好理解,我们通过下面一个例子来看看什么是属性值标准化:
在写CSS样式的时候,我们在设置color属性值的时候,常常会用white、red等,但是这种值浏览器的渲染引擎不随意马虎理解,以是须要将所有值转换成渲染引擎随意马虎理解的、标准化的打算值,这个过程便是属性值标准化。
white标准化后的值为 rgb(255, 255, 255)
2.3 打算DOM树中每个节点的样式完成样式的属性值标准化后,就须要打算每个节点的样式属性,这个阶段CSS有两个规则我们须要清楚:
继续规则:每个DOM节点都包含有父节点的样式层叠规则:层叠是CSS的一个基本特色,是一个定义了如何合并来自多个源的属性值的算法。样式打算阶段是为了打算出DOM节点中每个元素的详细样式,在打算过程中须要遵守CSS的继续和层叠两个规则。
该阶段终极输出的内容是每个DOM节点的样式,并被保存在 ComputedStyle 的构造中。
3. 布局阶段经由上面的两个步骤,我们已经拿到了DOM树和DOM树中元素的样式,接下来须要打算DOM树中可见元素的几何位置,这个打算过程便是布局。
3.1 创建布局树在DOM树中包含了一些不可见的元素,例如 head 标签,设置了 display:none 属性的元素,以是我们须要额外构建一棵只包含可见元素的布局树。
构建过程:从DOM树的根节点开始遍历,将所有可见的节点加到布局树中,忽略不可见的节点。
3.2 布局打算
到这里我们就有了一棵构建好的布局树,就可以开始打算布局树节点的坐标位置了。从根节点开始遍历,结合上面打算得到的样式,确定每个节点工具在页面上的详细大小和位置,将这些信息保存在布局树中。
布局阶段的输出是一个盒子模型,它会精确地捕获每个元素在屏幕内的确切位置与大小。
4. 分层现在我们已经有告终构树,也知道了每个元素的详细位置信息,但是还不能开始绘制页面,由于页面中会有像3D变换、页面滚动、或者用 z-index 进行z轴排序等繁芜效果,为了更方便实现这些效果,渲染引擎还须要为特定的节点天生专用的图层,并天生一棵对应的图层树(LayerTree)。
在Chrome浏览器中,我们可以打开开拓者工具,选择 Elements-Layers 标签,就可以看到页面的分层情形,如下图所示:
浏览器的页面实际上被分成了很多图层,这些图层叠加后合成了终极的页面。
到这里,我们构建了两棵树:布局树和图层树。下面我们来看下这两棵树之间的关系:
正常情形下,并不是布局树的每个节点都包含一个图层,如果一个节点没有对应的图层,那么这个节点就从属于父节点的图层。
那节点要知足什么条件才会被提升为一个单独的图层?只要知足下面个中一个条件即可:
拥有层叠高下文属性的元素会被提升为单独的一个图层须要剪裁(clip)的地方也会被创建为图层。5. 图层绘制构建好图层树之后,渲染引擎就会对图层树中的每个图层进行绘制。
渲染引擎实现图层绘制,会把一个图层的绘制拆分成很多小的绘制指令,然后将这些指令按照顺序组成一个绘制列表。
6. 栅格化(raster)操作绘制一个图层时会天生一个绘制列表,这只是用来记录绘制顺序和绘制指令的列表,实际上绘制操作是由渲染引擎中的合成线程来完成的。
通过下图来看下渲染主线程和合成线程之间的关系:
当图层的绘制列表准备好后,主线程会把该绘制列表提交给合成线程,合成线程开始事情。
首先合成线程会将图层划分为图块(tile),图块大小常日是 256256 或者 512512。
然后合成线程会按照视口附近的图块来优师长西席成位图,实际天生位图的操作是由栅格化来实行的。所谓栅格化,是指将图块转换为位图。而图块是栅格化实行的最小单位。渲染进程掩护了一个栅格化的线程池,所有的图块栅格化都是在线程池内实行的,运行办法如下图所示:
7. 合成和显示
一旦所有图块都被光栅化,合成线程就会天生一个绘制图块的命令——“DrawQuad”,然后将该命令提交给浏览器进程。
浏览器进程里面有一个名字叫做 viz 的组件,用来吸收合成线程发过来的 DrawQuad 命令,然后根据命令实行。 DrawQuad 命令,将其页面内容绘制到内存中,末了再将内存显示在屏幕上。
多年开拓老码农福利赠予:网页制作,网站开拓,web前端开拓,从最零根本开始的的HTML+CSS+JavaScript。jQuery,Vue、React、Ajax,node,angular框架等到移动端小程序项目实战【视频+工具+电子书+系统路线图】都有整理,须要的伙伴可以私信我,发送“前端”等3秒后就可以获取领取地址,送给每一位对编程感兴趣的小伙伴
8. 总结一个完全的渲染流程可以总结如下:
1、渲染进程将HTML内容转换为浏览器能够读懂的DOM树构造。2、渲染引擎将CSS样式表转化为浏览器可以理解的styleSheets,打算出DOM节点的样式。3、创建布局树,并打算所需元素的布局信息。4、对布局树进行分层,并天生分层树。5、为每个图层天生绘制列表,并将其提交到合成线程。6、合成线程将图层分图块,并栅格化将图块转换成位图。7、合成线程发送绘制图块命令给浏览器进程。浏览器进程根据指令天生页面,并显示到显示器上。渲染过程中还有两个我们常常听到的观点:重排和重绘。在这篇文章中就不细说了,下一篇文章再详细先容。