浏览器如何渲染页面
浏览器是多进程的
- 浏览器进程:控制除tab标签页外的用户界面,包括地址栏,书签,后退前进按钮,以及于浏览器其他进程协调工作
 - 渲染器进程:用来控制显示在tab页内的所有内容
 - GPU进程:负责整个页面的渲染
 - 网络进程:负责发起和接受网络请求
 - 缓存进程:负责浏览器缓存
 - 插件进程:负责控制网页使用的插件,例如flash
 
地址栏中输入内容
地址栏中输入内容,浏览器进程的UI线程会捕获输入的内容,如果访问的是网址,UI线程将启动一个网络线程,发起网络请求,请求DNS域名解析,找到服务器,与服务器建立TCp连接,发送http请求,获取到资源。如果不是网址,默认使用搜索引擎搜索。
浏览器获取到资源后,安全校验
会通过safeBtowsing检查是否是恶意站点,如果是将展示一个警告页
数据通过安全校验后
网络线程通知UI线程,然后UI线程会创建一个渲染器进程来渲染页面,浏览器进程通过IPC管道,将数据传给渲染器进程
渲染流程 => DOM树
html首先经过tokeniser标记化,通过词法分析将输入的html内容解析成多个标记,根据识别后的标记进行DOM树构造,在DOM树构造过程中创建document对象,然后以document为根节点的DOM树不断进行修改,向其中添加各种元素,这样就会获得一个DOM树
渲染流程 => DOM树 => 样式计算
主线程需要解析CSS,并确定每个DOM节点的计算样式,即使没有定义样式,浏览器定义的也有默认样式表
渲染流程 => DOM树 => 样式计算 => layout布局
主线程通过遍历dom和计算好的样式,来生成layout树,layout树的每个节点都记录了x,y坐标和边框尺寸
渲染流程 => DOM树 => 样式计算 => layout布局 => 绘制
还需要知道以什么样的顺序绘制节点,例如z-index属性会影响节点的绘制的层级关系所以为了展示正确的层级,主线程遍历layout树绘制一个绘制记录表,该表记录了绘制的顺序,这个阶段称为绘制
渲染流程 => DOM树 => 样式计算 => layout布局 => 绘制 => layer tree
主线程遍历Layout 树,生成layer树,当layer树生成完毕和绘制顺序确定后,主线程将这些信息传递给合成器线程
合成器线程和栅格化线程
把这些信息转化为像素点,显示在屏幕上,这种行为称为栅格化,chrome使用了一种更为复杂的栅格化流程,叫做合成,合成是一种将页面的各个部分分成多个图层,分别对其进行栅格化,并在合成器线程中单独进行合成页面。合成器线程按照规定进行分图层,并把图层分成更小的图块(tiles)传给栅格线程进行栅格化,栅格化完成后,合成器线程会获得栅格线程传过来的(draw quads)图块信息,根据这些信息合成器上合成了一个合成器帧
展示到屏幕
然后该合成器帧通过IPC传回给浏览器进程,浏览器进程再传到GPU进程进行渲染,之后就展示到屏幕上了
渲染流程图:

注意:DOM树和layout树结构不完全相同
DOM树和layout树并不是一一对应的,例如dipay:none的节点不会出现在layout树上。而在:after :before伪类中添加content值的元素,会出现在layout树上但不会出现在DOM树里
重排和重绘
- 当改变一个元素的尺寸位置属性时,会重新进行样式计算,布局(layout)绘制(paint)以及后面的所有流程,这种行为称为重排
 - 当改变样式时,不会触发布局,但还是会触发样式计算和绘制(layer),这个就是重绘
 - 重排和重绘都会占用主线程,JS也是运行在主线程上,就会出现抢占主线程,如果写了一个一直重排重绘的动画,当在一帧(每秒六十帧,16ms)的时间内布局和绘制结束,还有剩余时间,js就会抢占主线程,当在下一帧开始动画,JS没有及时归还,就会出现页面卡顿。
 
transform实现动画
页面的动画效果使用transform,减少重排和重绘,因为transform不是运行在渲染器进程的主线程上,运行在合成器线程和栅格化线程上。
参考:B站UP主视频---objtube的卢克儿
                    
                
                
            
        
浙公网安备 33010602011771号