久流
浏览器渲染
渲染 英文:Render 浏览器渲染本质是 Html字符串 - 渲染 -> 像素信息 可以理解为一个接收html字符串 输出像素信息的函数
当浏览器的网络线程接收到HTML文档之后,会产生一个渲染任务,并将其传递给渲染主线程的消息队列。在事件循环的作用下,渲染主线程取出消息队列中的渲染任务,开启渲染流程。
整个渲染流程分为多个阶段 如:HTML解析,样式计算,布局,分层,绘制,分块,光栅化,画。每个阶段都会有明确的输入输出,上一个阶段的输出会变成下一个阶段的输入。
解析HTML Parse HTML
解析HTML字符串
HTML字符串 -> Parse HTML -> DOM树 和 CSSOM树 (对象) 渲染主线程遇到JS的时候必须暂停一切行为等待下载完成后才能继续,预解析线程可以分担一点下载JS的任务。
解析CSS CSSOM树
CSS代码 -> 解析CSS -> Style Sheet List(样式表 根节点,也是对象 树形结构) 对象结构名字叫CSS Object Model(CSSOM)
解析过程中遇到CSS解析CSS,遇到JS解析JS。为了提高效率,浏览器在开始解析之前,会启动一个预解析的线程,预先下载 HTML 中的外部CSS文件和外部JS文件。
如果主线程解析到 Link 位置,此时外部的CSS文件还没有下载解析好,主线程不会等待,继续解析后面的HTML。这是因为下载和解析CSS的工作实在预解析线程中进行的。这是CSS不会阻塞HTML的根本原因。
如果主线程解析到 script 位置,会停止解析HTML,等待JS文件下载好,并将全局代码解析执行完成后,才能继续解析HTML。这是因为JS代码的执行过程可能会修改当前DOM树,所以DOM树的生成必须暂停。这就是JS会阻塞HTML解析的根本原因
第一步完成后,会得到DOM树和CSSOM树,浏览器的默认样式,内部样式,外部样式,行内样式均会包含在CSSOM树中。
样式计算 Computed Style
DOM树和CSSOM树经过样式计算合并在一起形成一个整体的DOM树 计算后的样式包含所有的默认样式同时是绝对单位
主线程会遍历得到的DOM树,依次为树冲的每个几点计算它最终的样式,称之为Computed Style。
在这一过程中,很多预设值会变成绝对值,比如 red 会变成 RGB(255,0,0); 相对单位会变成绝对单位,比如 em 会变成 px 。这一步完成后,会得到一个带有样式的DOM树。
布局 Layout
通过DOM树生成Layout树(Layout树属于C++对象 JS是获取不到的,但是树会暴露部分信息),计算结果是每个节点的尺寸和位置(包含块)
布局完成后会得到布局树。布局阶段会一次遍历DOM树的每一个节点,计算每个节点的几何信息。比如树的宽高,相对包含块的位置。
大部分时候 DOM 树和布局并非一一对应。比如 display:none 的节点就没有几何信息,因此不会生成到布局树,又比如使用了伪元素选择器,虽然 DOM 树中不存在这些伪元素节点,但它们拥有集合信息,所以会生成在布局树中。还有匿名块盒,匿名行盒等等都是会导致DOM树和布局树无法对应。
分层 Layers
主线程会单独使用一套复杂的策略对整个布局树中进行分层。
分层的好处在于,将来的某一个层改变后,仅会对该层进行后续处理,从而提高效率。滚动条,堆叠上下文,transform,opacity等样式都会或多会少的影响分层结果,也可以通过will-change属性更大程度的影响分层结果。
绘制 Paint
这里的绘制,是为每一层生成如何绘制的指令。渲染主线程的工作就到此为止,剩余的步骤交给其他线程完成(渲染主线程:parse,style,layout,layer,paint。 其他线程:后续步骤)。
主线程会为每个层单独产生绘制的指令集,用于描述这一层的内容该如何画出来。
分块 Tiling
完成绘制后,主线程会将每个图层的绘制信息提交给合成线程,剩余的工作交给合成线程完成。合成线程首先会对每个图层进行分块,将其划分更小的区域,它会从线程池中拿多个线程进行分块工作。主要是提高效率。
光栅化 Raster
光栅化是将每个块变成位图,优先处理靠近视口的块。是从合成线程中转到GPU进程(调用GPU加速)进行光栅化然后将位图传到合成线程。
合成线程会将信息交给GPU进程,用极高的速度进行光栅化。GPU进程会开启多个线程(内部实现)完成光栅化,并且优先处理靠近视口区域的块。光栅化的结果,就是一块一块的位图。
画 Draw
合成线程拿到每个层每个块的位图后,生成 指引(quad) 信息。指引会标出每个位图应该画在屏幕的哪个位置,以及考虑旋转,缩放等变形。
变形发生在合成线程(矩阵变换),与渲染主线程无关,这个就是 transform 效率高的本质原因。合成线程会把 quad 提交给 GPU 进程,由 GPU 进程产生系统调用,提交给GPU硬件,完成最终的屏幕成像。
暂无评论