渲染流程

浏览器渲染流程详细版

DOM树构建

渲染器进程接受到的数据也就是HTML.渲染器进程的核心任务就是把html、css、js、image等资源渲染成用户可以交互的web页面.DOM也就是文档对象模型,是浏览器对页面在其内部的表示形式,是web开发程序员可以通过JS与交互的数据结构和API.html首先通过tokeniser标记化,通过词法分析将输入的html内容解析成多个标记,根据识别后的标记进行dom树构建,在DOM树构建过程中会创建document对象,然后以document的为根节点的DOM树,不断的进行修改,向其中添加元素

渲染阻塞

html代码中往往会引入一些额外的资源,比如图片、CSS、JS脚本等, 图片和CSS这些资源需要通过网络下载或从缓存中直接加载,这些资源不会阻塞html的解析,因为它们不会影响DOM树的生成,但当HTML解析过程中遇到script标签,就会停止html解析流程,转而去加载过程中遇到的script标签,就会停止html解析流程,转而去加载解析并且执行js.这是因为浏览器并不直到js执行是否会改变当前页面的HTML结构, 如果js代码里面用到了docuemnt.write方法来修改html,之前的和html解析就没有任何关系了,这也就是为什么我们一直说要把script标签要放到合适的位置,或是使用async或defer属性来异步加载执行js

Layout Tree

在html解析完成后,我们就会获得一个DOM Tree, 但是我们还不知道DOM Tree上的每个节点应该长什么样子,主线程需要解析css,并确定每个节点的计算样式,及时你没有提供自定义的css样式, 浏览器会有自己默认的样式表,比如h2的字体要比h3的字体大.在直到DOM结构和每个节点的样式后,我们接下来需要知道每个节点需要坊在页面的哪个位置上,也就是节点的坐标以及该节点需要占用多大的区域,这个阶段被成为layout布局,主线程通过遍历dom和计算好的样式来生成Layout Tree, Layout Tree上的每个节点都记录了x,y坐标和边框尺寸.这需要注意的是DOM Tree和Layout Tree 并不是 — 对应的,设置了display:none的节点不会出现在Layout Tree中,而在before伪类中添加content值的元素content中的内容会出现在LayoutTree中,不会出现在DOM树中,这是因为DOM是通过HTML解析获得的,并不关系样式,而LayoutTree是根DOM和计算好的样式来生成,Layout Tree和最后显示在屏幕上的节点是对应的

绘制(Paint)

现在我们已经知道了元素的大小形状和位置,但还不知道什么样的顺序绘制(paint)这个节点, 例如 z-index 这个属性会影响即诶单绘制的层次关系,如果按照dom的层次结构来绘制页面会导致错误渲染, 所以为了保证在屏幕上展示正确的层级,主线程遍历Layout Tree创建一个绘制记录表(Paint Record),该表记录了绘制顺序,这个阶段配称为绘制(Paint)

栅格化

现在知道了文档的绘制顺序,终于到了该把这些信息转换称像素点显示在屏幕上了,这个行为被称为栅格化(Rastering) chrome最早使用了一种很简单的方式,只栅格化用户可视区域的内容,当用户滚动页面时,再栅格化更多的内容来填充确缺失的部分,这种方式带来的问题就是会导致展示延迟,现在chrome进行了优化升级,使用了更为复杂的栅格化流程叫做合成(compositing), 合成是一种将页面各个部分分成多个图层,分别对其进行栅格化,并在合成线程(Composition Thread) 中单独进行合成页面, 简单来说就是页面所有的元素按照某种规则进行分图层,并把图层都栅格化好了,然后只需要把可是区域的内容组合成一帧展示给用户即可

Layer Tree

主线程遍历Layout Tree 生成 layer Tree ,当 layer Tree 生成完毕和绘制循序确定后, 主线程会将这些信息传递给合成器线程,合成器线程将每个图层栅格化,由于一层可能想页面的整个长度一样大,因此合成器线程将它们切分成许多图块(tiles), 然后将每个图块发送给栅格化线程(Raster Thread) , 栅格化线程栅格化每个图块,并将他们存储在CPU内存中,当图块栅格化完成后,合成器线程将收集成为draw quads 的图块信息, 这些信息里记录了图块字段内存中为位置和页面的那个位置绘制图块的信息, 根据这些悉尼下合成线程生成一个合成器帧(Compositor Frame) 然后合成Frame(帧)通过IPC传递给浏览器进程,接着浏览器进程将合成帧传送到GPU, 然后GPU渲染展示到屏幕上

当页面发生变化时,比如滚动了当前页面,都会生成一个新的合成器帧,新的合成器再传给GPU, 然后再次渲染到屏幕

浏览器渲染流程简要版本

  1. html解析生成DOM树
  2. 遇到css时,css解析器将计算并生成cssDOM
  3. 将DOM树和cssDOM树合成渲染树,并计算元素布局信息
  4. 将渲染树生成合成树
  5. 将渲染主线程生成渲染绘制指令列表提交给合成器线程
  6. 合成器线程利用栅格化生成位图,此时会用GPU进程来进行加速
  7. 提交给浏览器主进程进行页面展示