浏览器页面的渲染流程

在上一篇当中《从输入URL到⻚面展现,这中间发生了什么?》最重要的过程是在页面的渲染。这一篇咱们来梳理一下渲染流程。浏览器

首先咱们先熟悉页面“三剑客”——HTML、CSS、JavaScript。HTML全称是超文本标记语言,俗称标签;CSS全称是层叠样式表,俗称样式;JavaScript是浏览器的脚本语言,使用脚本可使内容“动”起来,简称JS性能优化

熟悉完三剑客后,来看看浏览器的渲染机制。它的过程较于复杂,在执行的过程中会被划分为多个子阶段,咱们把处理一系列子阶段的流程称之为渲染流水线。咱们不必去熟悉每一个子阶段,只需了解其中几个重要的子阶段过程:数据结构

先是DOM树样式计算、建立布局树、进行分层为分层树、再进入合成线程、造成图块进行光栅化转为位图、最后浏览器进程根据命令DrawQuad生成页面显示出来。工具

DOM树

对于DOM树相信咱们并不陌生,咱们经常听到且在浏览器console里面输入document能够打印出来看获得。 布局

DOM数构建过程示意图

样式计算(Recalculate Style)

浏览器不只须要将HTML转成能够识别的DOM树结构,并且相应的CSS样式也须要转化能够识别的结构stylesheet。其实咱们能够在浏览器开发者工具console标签处输入document.styleSheets,就能够看到以下图所示: 性能

至于样式计算还有关于样式属性标准化层叠规则的延展,此处就不作过多输出,感兴趣的话能够搜索加深了解。优化

布局阶段(Layout)

顾名思义,布局就是浏览器按照DOM树和styleSheets数据结构开始布局计算,正如咱们搭建房子,把设计图纸画好后再动手搭建。动画

分层-图层树(LayerTree)

当觉得布局好了就能够渲染页面时,居然不知浏览器还需作下一步工做,即分层。由于页面中有不少复杂的效果,如一些复杂的3D变换、页面滚动,或者使用z- indexing作z轴排序等,为了更加方便地实现这些效果,**渲染引擎还须要为特定的节点生成专用的图层,并生成一棵对应的图层树(LayerTree)。**比如PS(PhotoShop)软件里面的图层概念,正是这些图层叠加在一块儿构成 了最终的页面图像。 熟悉了图层,再来看为何浏览器还不能渲染页面,那是由于图层树须要和布局树结合,也叫合成composition线程

布局树和图层树关系示意图

结合上图的布局树和图层树的关系示意图,这里帮助笔者疏通了CSS样式当中层叠上下文的知识点。由于拥有层叠上下文属性的标签会被提高为单独的一层设计

图层绘制(paint) 图层树造成后还须要图层绘制(paint),咱们也能够打开浏览器的开发者工具的“layer”标签,选择“document”层,来实际体验下绘制列表,以下图所示:

在图中,区域1就是document的绘制列表,拖动区域2中的进度条能够重现列表的绘制过程。

栅格化(raster)

要明白栅格化,先要理解什么是图块和位图。首先图块(tile)是渲染进程即浏览器内核当中的合成线程将图层划分为大小512x512或者256x256的区块

其次位图则是栅格化的过程:合成线程会按照视口附近的图块来优先生成位图,实际生成位图的操做是由栅格化来执行的,将图块转换为位图

显示(DrawQuad)

一旦全部图块都被光栅化,合成线程就会生成一个绘制图块的命令——“DrawQuad”,而后将该命令提交给浏览器进程处理,最终将页面display呈现出来。

渲染流水线大总结

至此已经分析完整个渲染流程,从HTML到DOM、样式计算、布局、图层、绘制、光栅化、合成和显示。下面一张图是总结下这整个渲染流程:

结合上图,一个完整的渲染流程大体可总结为以下:

  1. 渲染进程将HTML内容转换为可以读懂的DOM树结构。
  2. 渲染引擎将CSS样式表转化为浏览器能够理解的styleSheets,计算出DOM节点的样式。
  3. 建立布局树,并计算元素的布局信息。
  4. 对布局树进行分层,并生成分层树
  5. 为每一个图层生成绘制列表,并将其提交到合成线程。
  6. 合成线程将图层分红图块,并在光栅化线程池中将图块转换成位图。
  7. 合成线程发送绘制图块命令DrawQuad给浏览器进程。
  8. 浏览器进程根据DrawQuad消息生成页面,并显示到显示器上。

当咱们把浏览器内核工做流程熟悉后再回过头看性能优化当中经常提到的“重排”、“重绘”和“合成”,相信就能够理解更加透彻一点了。

重排是更新了元素的几何属性,例如改变了元素的宽高,会触发浏览器从新渲染流程,解析以后的一系列子阶段,因此说重排会致使开销最大

重绘是更新元素的绘制属性,例如元素的背景色,不会引发元素的几何位置变化,就直接进入了绘制阶段,而后执行以后的一系列子阶段。因此相对重排来讲,执行效率会高一些,由于省去了布局计算和分层阶段。

合成是改了元素的既不布局也不绘制的属性,例如transform实现动画效果,避开重排和重绘阶段,直接在非主线程上 执行合成动画操做。这样的效率是最高的,由于是在非主线程上合成,并无占用主线程的资源,另外也避开了布局和绘制两个子阶段,因此相对于重绘和重排,合成能大大提高绘制效率。

经过整理来自极客时间课程《浏览器工做原理与实践》笔记,对浏览器的渲染进程了解更加深刻,对于页面从URL到展示的过程了然于胸,强迫本身作笔记仍是蛮有收获滴~但愿笔记能够帮助到你们。