导航菜单

搜索并跳转到页面

前端2026年3月27日
浏览器渲染的实现

久流

浏览器渲染

渲染 英文: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硬件,完成最终的屏幕成像。


评论
0 个评论在此篇文章

暂无评论