客户端容器 | 青训营笔记

36 阅读4分钟

1. 浏览器架构

1.1 浏览器架构演进

  • 单进程架构:所有模块运行在同一个进程里,包含网络、插件、javascript运行环境等
  • 多进程架构:主进程、网络进程、渲染进程、GPU进程、插件进程
  • 面向服务架构:将原来的UI、数据库、文件、设备、网络等,作为一个独立的基础服务

1.2 浏览器架构对比

架构类型扩展性安全性稳定性流畅度
单进程架构卡顿
多进程架构流畅
面向服务架构流畅

1.3 多进程分工

进程名称进程描述
浏览器(主进程)主要负责页面展示逻辑,用户交互,子进程管理;包括地址、书签、前进、后退、收藏夹等
CPU进程负责UI绘制,包括整个浏览器全部UI
网络进程网络服务进程,负责网络资源加载
标签页(渲染进程)控制tab的所有内容,将Html、CSS、JavaScript转换为用户可交互的网页
插件进程控制网站运行的插件,比如flash、ModHeader等
其他进程适用程序Storage、Network、Audio Service等

2. 渲染进程

内部是多线程实现,主要负责页面渲染,脚本执行,事件处理,网络请求等

线程功能
JS引擎负麦解析js脚本,运行js程序,每个渲染进程下面只有一个js引擎线程。与GUI渲染线程互斥,如果js任务执行时间过长,会导致页面卡顿
GUI渲染负责渲染浏览器界面,解析html、css,构建dom树和render树、布局、绘制,和js引擎线程互斥,GUI更新会在js引擎空闲时立即执行
定时器触发定时器所在线程,setTimeout、setInterval计时完毕后,将回调添加到事件队列,等待js引擎执行
网络线程在XHR、 Fetch等发起请求后新开一个网络线程请求,如果设置了回调函数,在状态变更时,将回调放入事件队列,等待js引擎执行
事件触发由宿主环境提供,用于控制事件循环,不断地从事件队列里取出任务执行

练习

const now = Date.now();
setTimeout(() => {
    console.log('time10', Date.now()-now);
}, 10);

setTimeout(() => {
    console.log('time30', Date.now()-now);
}, 30);

while (true) {
    if(Date.now() - now >= 20){
        break;
    }
}

console.log(Date.now() - now);

输出结果为

20
time10 21
time30 31

定时器的本质,就是在指定时间后将函数添加到消息队列中。

3. Chrome运行原理

3.1 输入处理

  • 用户在url输入内容后,UI线程会判断输入的是一个url地址还是一个query查询条件
  • 如果是url,直接请求站点资源
  • 如果是query,将输入发送给搜索引擎

3.2 开始导航

  • 用户按下回车,UI线程通知网络线程发起一个网络请求,来获取站点内容
  • 请求过程中,tab处于loading状态

3.3 读取响应

  • 网络线程接收到HTTP响应后,先检查响应头的媒体类型(MIME Type)
  • 如果响应主体是一个HTML文件,浏览器将内容交给渲染进程处理
  • 如果拿到的是其他类型文件,比如Zip、exe等,则交给下载管理器处理

3.4 寻找渲染进程

  • 网络线程做完所有检查后,会告知主进程数据已准备完毕,主进程确认后为这个站点寻找一个渲染进程
  • 主进程通过IPC消息告知渲染进程去处理本次导航
  • 渲染进程开始接收数据并告知主进程自己已开始处理,导航结束,进入文档加载阶段

3.5 资源加载

  • 收到主进程的消息后,开始加载HTML文档
  • 除此之外,还需要加载子资源, 比如一些图片,CSS样式文件以及JavaScript脚本

3.6 构建渲染树

  • 构建DOM树,将HTML文本转化成浏览器能够理解的结构
  • 构建CSSOM树,浏览器同样不认识CSS,需要将CSS代码转化为可理解的CSSOM
  • 构建渲染树,渲染树是DOM树和CSSOM树的结合

3.7 页面布局

  • 根据渲染树计算每个节点的位置和大小
  • 在浏览器页面区域绘制元素边框
  • 遍历渲染树,将元素以盒模型的形式写入文档流

3.8 页面绘制

  • 构建图层:为特定的节点生成专用图层
  • 绘制图层:一个图层分成很多绘制指令,然后将这些指令按顺序组成一个绘制列表,交给合成线程
  • 合成线程接收指令生成图块
  • 栅格线程将图块进行栅格化
  • 展示在屏幕上