一、浏览器结构(简化)
1. 用户界面
展示除标签页窗口之外的其他用户界面内容
2. 浏览器引擎
用于在用户界面和渲染引擎之间传递数据
3. 渲染引擎
负责渲染用户请求的页面内容
二、多进程浏览器(chrome为例)
可大致拆分为
1. 浏览器进程
2. 缓存进程
3. 网络进程
4. 渲染器进程
浏览器会在默认情况为每个标签页创建一个进程
- Process-per-site-instance(默认)
访问不同站点和同一站点的不同页面都会创建新的进程 - Process-per-site
同一站点使用同一进程 - Process-per-tab
一个tab里的所有站点使用一个进程 - Single process
让浏览器引擎和渲染引擎共用一个进程
5. GPU进程
6. 插件进程
三、在地址栏输入内容时浏览器内部变化
- 输入网址时
- UI线程启动一个网络线程请求DNS进行域名解析然后连接服务器获取数据
- 输入关键字时
- 使用默认搜索引擎查询
- 检查站点是不是恶意站点
- 网络线程通知UI线程,然后UI线程创建一个渲染器进程渲染页面
- 浏览器进程将数据传递给渲染器进程,正式进入渲染流程
- 渲染器进程的主线程将html进行解析,构造DOM数据结构(html通过Tokeniser标记化,通过词 法分析将输入的html将解析成多个标记,据此进行DOM树(以document为节点)构造)。构造过程中的其他资源如css、图片等一般不会阻塞html解析。但遇到script标签会停止解析,转而加载解析执行js
- 解析完后获得DOM树,主线程解析css,确定DOM节点计算样式
- 主线程通过遍历dom和计算好的样式生成layout树(DOM树节点不一定与layout树节点一一对应)
- 主线程遍历layout树生成layer树(图层树)并确定绘制顺序后,再传递给合成器线程
- 合成器线程将图层栅格化,并切分为许多图块,再将每个图块发送给栅格化线程,栅格完后存在GPU内存中,结束后合成器线程收集图块信息,据此生成合成器帧,通过IPC(进程间通信)传给浏览器进程
- 浏览器进程将帧传给GPU,
- GPU渲染到屏幕上
重排和重绘
重排:改变一个元素的尺寸位置属性时,会重新计算样式、布局、绘制及以后的所有流程
重绘:改变某个元素的颜色属性时触发样式计算和绘制
为什么要避免重绘和重排?:都在主线程上运行,会与JS抢占执行时间。当频繁发生重排和重绘时,JS运行时间较长的话,有可能会阻塞主线程,导致掉帧(前一帧绘制完成后,在这一帧剩余时间开始运行js,若运行到了下一帧的时间,则影响下一帧的绘制)
优化手段:
- 可以通过requestAnimationFrame(),将JS任务分成更小的任务块分到每一帧,在每一帧时间用完前暂停JS执行交还主线程
- 使用transform动画:不在主线程执行,而在合成器线程和栅格线程执行。不经过样式计算和布局绘制,节省运算时间