一、Chrome多进程架构
作者:五柳
链接:https://juejin.cn/post/6844904114506170381
来源:掘金
首先,在开始讲解整个过程前,我们需要认识一下Chrome
多进程架构。因为,从浏览器输入URL到页面渲染的整个过程都是有Chrome
架构中的各个进程之间配合完成。
Chrome
的多进程架构
- 浏览器进程:它负责用户界面(地址栏、菜单等等)、子进程的管理(例如,进程间通信和数据传递)、存储等等
- 渲染进程:它负责将接收到的
HTML
文档和JavaScript
等转化为用户界面 - 网络进程:它负责网络资源的请求,例如
http
请求、webstocket
模块 GPU
(图形处理器)进程:它负责对UI
界面的展示- 插件进程:负责对插件的管理
二、过程详解
2.1解析输入
发生这个过程的前提,用户在地址栏中输入了URL,而地址栏会根据用户输入,做出如下判断:
- 输入的时非
URL
结构的字符串,则会用浏览器默认的搜索引擎搜索该字符串 - 输入的时
URL
结构字符串,则会构建完成的URL
结构,浏览器进程会将完整的URL
通过进程间通信,即IPC
,发送给网络进程
2.2请求过程
在网络进程接收到URL
后,并不是马上对指定的URL
进行请求。首先,我们需要将DNS
解析域名得到对应的IP
,然后通过ARP
解析IP
对应的MAC
(Media Access Control Address
)地址。
域名是我们取代记忆复杂的
IP
的一种解决方案,而IP
才是目标在网络中所被分配的节点。MAC
地址是对应目标网卡所在的固定地址。
1.DNS解析
DNS解析域名的过程分为以下几个步骤:
- 询问浏览器DNS缓存
- 询问本地操作系统DNS缓存(即查找本地host文件)
- 访问ISP(Internet Service Provider)互联网服务提供商(例如电信、移动)的DNS服务器
- 访问根服务器,这个过程可以进行递归和迭代两种查找方式,两者都是先询问顶级域名服务器查找
2.通信过程
首先,建立TCP
连接,即三次握手过程
- 客户端发送标有
SYN
的数据包,表示我将要发送请求。 - 服务端发送标有
SYN/ACK
的数据包,表示我已经收到通知,告知客户端发送请求 - 客户端发送标有
ACK
的数据包,表示我要开始发送请求,准备被接收。
然后,利用TCP
通道进行数据传输: - 服务端接收到数据包,并发送确认数据包已收到消息到客户端,不断重复这个过程
- 客户端在发送一个数据包后,未接收到服务器的确定消息,则重新发送该数据包,即TCP的重发机制
- 当接收完所有数据包后,接收端会按照TCP头中的需要进行排序,形成完整的数据
最后,断开TCP
连接,即四次握手过程
- 客户端发送请求,申请断开连接,进入等待阶段,此时不会发送数据,但是会继续接受数据
- 服务端接收请求后,告知客户端已明白,此时服务端进入等待状态,不会再接收数据,但是会继续发送数据
- 客户端收到后,进入下一阶段等待
- 服务端发送完剩余的数据后,告知客户端可以断开连接,此时服务端不会发送和接收数据
- 客户端收到后,告知服务端我开始断开连接
- 服务端收到后,开始断开连接
而这整个过程的客户端则是网络进程。并且在数据传输的过程还可能会发生的重定向情况,即当网络进程接收到状态码为3xx的响应报文,则会根据影响报文首部字段中的Location字段的值进行重定向,即会重新发送请求
3.数据处理
当网络进程接收到响应报文状态码,进行相应的操作。例如状态码为200
ok时,会解析响应报文中的Content-Type
首部字段,例如我们这个过程Content-Type
会出现application/javascript
、text/css
、text/html
,即对应 Javascript
文件、CSS
文件、HTML
文件。
2.3创建渲染进程
当前需要渲染HTML时,则需要创建渲染进程,用于后期渲染HTML。而对于渲染进程,如果时统一站点时可以共享一个渲染进程,例如a.abc.com和c.abc.com可以共享一个渲染进程,否则,需要重新创建渲染过程
需要注意的时,同站指的是顶级域名和二级域名相等
2.4开始渲染
在创建完渲染进程后,网络进程会将接收到的HTML
、JavaScript
等数据传输给渲染进程。而在渲染进程接收完数据后,此时用户界面会发生这几件事:
- 更新地址栏的安全状态
- 更新地址栏的
URL
- 前进后退此时
enable
,显示正在加载状态 - 更新网页
2.5渲染过程
大家都知道页面渲染的过程也是面试中但对会考的点,并且时常会由整点延伸出另一个问题,即如何避免回流和重绘。
渲染过程,是整个从浏览器输入URL
到页面渲染过程的最后一步。而页面渲染的过程可以分为9个步骤
- 解析
HTML
生成DOM
树 - 解析
CSS
生成CSSOM
- 加载或执行
JavaScript
- 生成渲染树(
Render Tree
) - 布局
- 分层
- 生成绘制列表
- 光栅化
- 显示
2.5.1构建DOM树
由于网络进程传输给渲染进程的是HTML
字符串,所以渲染进程需要将HTML
字符串转换成DOM
树
需要注意的是这个
DOM
树不同于Chrome-devtool
中的Element
选项卡的DOM
树,它是存在内存中,用于提供JavaScript
对DOM
的操作。
2.5.2构建CSSOM
构建CSSOM
的过程,即通过解析CSS
文件、style
标签、行内style
等,生成CSSOM
。而这个过程会做一下几件事
- 规范
css
,将color:blur
转化成color:rgb()
形式,可以理解成类似ES6
转ES5
的过程 - 计算元素样式,例如
CSS
样式会继承父级样式,如font-size
、color
之类的
CSS Object Model
是一组允许用JavaScript
操纵CSS
的API
。详细API
讲解可以看MDN
2.5.3加载JavaScript
通常情况下,在构建DOM
树或CSSOM
的同时,如果也要加载JavaScript
,则会造成前者的构建暂停。当然,我们可以通过defer
或sync
来实现异步加载JavaScript
。虽然defer
和sync
都可以实现异步加载JavaScript
,但是前者(defer
)是在加载后,等待CSSOM
和DOM
树构建完后才执行JavaScript
,而后者(sync
)是在异步加载完马上执行,即使用sync
的方式依然会造成阻塞。而JavaScript
执行的过程,即编译和运行JavaScript
的过程。由于JavaScript
是解释性的语言。所以这个过程是这样的:
- 针对每句代码进行分行处理,即
Token
化 - 根据
Token
,生成AST
(Abstract Sytanx Tree
)抽象语法树和创建上下文 - 解释器解析核执行
AST
,生成字节码 - 编译器针对需要反复执行的代码,生成对应的机器码,提高运行效率
2.5.4生成渲染树(Render Tree
)
在有了DOM
树和CSSOM
之后,需要将两者结合生成Render Tree
,并且这个过程会去除掉那些display:none
的节点。此时,渲染树就具备元素和元素的样式信息。
2.5.5布局
根据Render Tree
渲染树,对树中每个节点进行计算,确定每个节点在页面中的宽度、高度和位置
需要注意的是,第一次确定节点的大小和位置的过程称为布局,而第二次才被称为回流
2.5.6分层
由于层叠上下文的存在,渲染引擎会为具备层叠上下文的元素创建对应的图层,而诸多图层的叠加就形成了我们看到的一些页面效果。例如,一些 3D
的效果、动画就是基于图层而形成的。
值得一提的是,对于内容溢出存在滚轮的情况也会进行分层
2.5.7生成绘制列表
对于存在图层的页面部分,需要进行有序的绘制,而对于这个过程,渲染引擎会将一个个图层的绘制拆分成绘制指令,并按照图层绘制顺序形成一个绘制列表。
2.5.8光栅化
有了绘制列表后,渲染引擎中的合成线程会根据当前视口的大小将图层进行分块处理,然后合成线程会对视口附近的图块生成位图,即光栅化。而渲染进程也维护了一个栅格化的线程池,专门用于将图块转为位图。
光栅化的过程通常会使用
GPU
加速,例如使用wil-change
、opacity
,就会通过GPU
加速显示
2.5.9显示
当所有的图块都经过栅格化处理后,渲染引擎中的合成线程会生成绘制图块的指令,提交给浏览器进程。然后浏览器进程将页面绘制到内存中。最后将内存绘制结果显示在用户界面上。
而这个整个从生成绘制列表、光栅化、显示的过程,就是我们常说的重绘的过程
结语
整个浏览器输入 URL
到页面渲染的过程涉及到的知识点非常广,如 Chrome
多进程的架构、HTTP
通信过程、浏览器解析 JavaScript
过程、浏览器绘制页面过程以及一些计算机的基础知识等等,并且,这整个过程的分析其实和 Chrome-devtools
密切相关,所以很好的使用 Chrome-devtools
是非常重要的,后续应该会出一篇关于使用 Chrome-devtools
的指南。当然,本篇文章仍然存在诸多不足,欢迎提issue ~
作者:五柳
链接:https://juejin.cn/post/6844904114506170381
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。