浏览器的渲染流程详解
大致分为渲染主线程和和成线程,如下图
一:主线程
1:解析html
解析html过程中遇到css解析css,遇到js执行js。为了提高解析的运行效率,浏览器在解析前会开启一个预解析的线程,优先下载html中的外部css和js。
如果主线程解析到link位置,外部css文件没有下载解析完,主线程不会等待,而是继续解析后面的html。这是因为下载和解析css的工作是在预解析线程中进行的。这就是css不会阻塞html解析的根本原因。
如果主线程解析到script位置,会停止解析html,转而等待js文件下载好,并将全局代码解析执行完成后才继续解析html。这是因为js代码在执行过程中会修改当前的dom树,所以dom树的生成必须暂停。这就是js会阻塞html解析的根本原因。
2:样式计算 (computed style)
主线程会遍历得到dom树,依次为dom树种的每个节点计算它最终的样式
3:布局
依次遍历所有的dom节点,计算每个节点的几何信息。例如节点的宽高,相对包含块的位置。需要注意的是:大部分时候,dom树和布局树并非一一对应。比如display: none没有几何信息,无法生成布局树。
相对包含块:简单来说子盒子距离父盒子margin-left为20px;那么这个父盒子就是子盒子的相对包含块。详细说明就是:假设有个十层嵌套的盒子,第10层是绝对定位,第一次是相对定位,那么第一次才是第10层的相对包含块。
4:分层
将布局树分层后,一个层的某一个东西改变了,那么就只会对这一层进行后续处理,从而提高渲染的效率。滚动条、transform、opacity等都会影响分层结果,也可以通过will-change来影响分层结果(不是直接改变结果,而是影响,直接改变结果是浏览器里面的做到事,你只能根据浏览器提供的方式来影响它)
谷歌浏览器如何看分层的,更多工具–>图层(如下图)
为了看到更多图层,使用了移动端的方式,有以下三层,第一层粉色部分的内容图层。第二层的横轴滚动条,第三层的纵轴滚动条(如下图)。
5:绘制
主线程为每一个分层产生一个单独的绘制指令集合。
二:合成线程
完成绘制后,主线程每个图层的绘制信息提交给合成线程,剩下的工作将由合成线程完成。
6:分块
合成线程中将每一分层分为多个小的区域,分块的工作是由多个线程同时进行的。
7:光栅化
分块完成后,合成线程将块信息交给GPU进程,以极快的速度完成光栅化。GPU进程会开启多个线程来完成光栅化,并优先处理视图区域的块。
8:画
合成线程在光栅化后获取一个一个的位图,生成一个【quad】指引信息。指引会标识哪个位图去屏幕的哪个位置,同时考虑旋转、缩放等变形。变形发生在合成线程,与渲染主线程无关,这也是transform效率高的本质原因。
GPU(图形处理器,)和CPU(中央处理器)的区别?
GPU处理指引信息比CPU是要快的,那为什么不都使用GPU呢?
简单理解:就是GPU就只能处理指引计算信息,而CPU能处理的东西比GPU能处理的多的多。因为会的少,所以学的精。
详细理解:GPU有大量的运算单元负责简单粗暴的计算 和 少量的控制单元和缓存单元负责合并和转发数据;CPU有少量的运算单元,强大的逻辑运算能力,需要足够的控制单元实现复杂的数据控制和数据转发和足够的缓存单元去存放一些已经计算完成的结果。