
来源 | https://www.cnblogs.com/AhuntSun-blog/p/12641050.html
从输入URL到页面渲染需要Chrome浏览器的多个进程配合,所以我们先来谈谈现阶段Chrome浏览器的多进程架构。
一、Chrome架构
目前Chrome采用的是多进程的架构模式,可分为主要的五类进程,分别是:浏览器(Browser)主进程、 GPU 进程、网络(NetWork)进程、多个渲染进程和多个插件进程;

浏览器进程。主要负责界面显示、用户交互、子进程管理,同时提供存储等功能。
渲染进程。核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎Blink和JavaScript引擎V8都是运行在该进程中,默认情况下,Chrome会为每个Tab标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。
GPU进程。其实,Chrome刚开始发布的时候是没有GPU进程的。而GPU的使用初衷是为了实现3D CSS的效果,只是随后网页、Chrome的UI界面都选择采用GPU来绘制,这使得GPU成为浏览器普遍的需求。最后,Chrome在其多进程架构上也引入了GPU进程。
网络进程。主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程。
插件进程。主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响
了解了Chrome的多进程架构,就能够从宏观上理解从输入URL到页面渲染的过程了,这个过程主要分为导航阶段和渲染阶段。
二、导航阶段
Ⅰ.浏览器主进程
1.用户输入URL
Ⅱ.网络进程
2.URL请求过程
这里涉及到浏览器与HTTP协议的缓存策略问题,有兴趣的可以看这篇文章:详解HTTP协议
4、准备IP地址和端口:进行DNS解析时先查找缓存,没有再使用DNS服务器解析,查找顺序为:
-
5、等待TCP队列:浏览器会为每个域名最多维护6个TCP连接,如果发起一个HTTP请求时,这 6个 TCP连接都处于忙碌状态,那么这个请求就会处于排队状态;解决方案:
采用域名分片技术:将一个站点的资源放在多个(CDN)域名下面。
升级为HTTP2,就没有6个TCP连接的限制了;
6、通过三次握手建立TCP连接:

标志位值为1表示该标志位有效。
这里要区分标志位ACK和确认号ack;
服务器端收到后,也进入ESTABLISHED状态,由此成功建立了TCP连接,可以开始数据传送;
如果没有最后一个数据包确认(第三次握手),A先发出一个建立连接的请求数据包,由于网络原因绕远路了。A经过设定的超时时间后还未收到B的确认数据包。
于是发出第二个建立连接的请求数据包,这次网路通畅,B的确认数据包也很快就到达A。于是A与B开始传输数据;
过了一会A第一次发出的建立连接的请求数据包到达了B,B以为是再次建立连接,所以又发出一个确认数据包。由于A已经收到了一个确认数据包,所以会忽略B发来的第二个确认数据包,但是B发出确认数据包之后就要一直等待A的回复,而A永远也不会回复。
由此造成服务器资源浪费,这种情况多了B计算机可能就停止响应了。
为什么要第三次挥手?避免服务器等待造成资源浪费,具体原因:
第三次:客户端收到后,再给服务器发送一个确认数据包,标志位ACK=1,序号seq=x+1,确认号ack=y+1,随后进入ESTABLISHED状态;
第二次:服务器根据收到数据包的SYN标志位判断为建立连接的请求,随后返回一个确认数据包,其中标志位SYN=1,ACK=1,序号seq=y,确认号ack=x + 1表示收到了客户端传输过来的x字节数据,并希望下次从x+1个字节开始传,并进入SYN-RCVD状态;
第一次:客户端先向服务器端发送一个同步数据包,报文的TCP首部中:标志位:同步SYN为1,表示这是一个请求建立连接的数据包;序号Seq=x,x为所传送数据的第一个字节的序号,随后进入SYN-SENT状态;
7、构建并发送HTTP请求信息;
8、服务器端处理请求;
9、客户端处理响应,首先检查服务器响应报文的状态码:
-


第一次:客户端(主动断开连接)发送数据包给服务器,其中标志位FIN=1,序号位seq=u,并停止发送数据;
第二次:服务器收到数据包后,由于还需传输数据,无法立即关闭连接,先返回一个标志位ACK=1,序号seq=v,确认号ack=u+1的数据包;
第三次:服务器准备好断开连接后,返回一个数据包,其中标志位FIN=1,标志位ACK=1,序号seq=w,确认号ack=u+1;
第四次:客户端收到数据包后,返回一个标志位ACK=1,序号seq=u+1,确认号ack=w+1的数据包。
由此通过四次挥手断开TCP连接。
详细过程参见:详解TCP连接的“三次握手”与“四次挥手”(上)
3.准备渲染进程
4.提交文档

三、渲染阶段
在渲染阶段通过渲染流水线在渲染进程的主线程和合成线程配合下,完成页面的渲染;
Ⅲ.渲染进程

渲染进程中的主线程部分
5.构建DOM树
渲染引擎还有一个安全检查模块叫 XSSAuditor,是用来检测词法安全的。在分词器解析出来 Token 之后,它会检测这些模块是否安全,比如是否引用了外部脚本,是否符合 CSP 规范,是否存在跨站点请求等。如果出现不符合规范的内容,XSSAuditor 会对该脚本或者下载任务进行拦截。
首次解析HTML时渲染进程会开启一个预解析线程,遇到HTML文档中内嵌的JavaScript和CSS外部引用就会同步提前下载这些文件,下载时间以最后下载完的文件为准。

6.构建CSSOM
优化方案:
移除js和css的文件下载:通过内联 JavaScript、内联 CSS;
尽量减少文件大小:如通过 webpack 等工具移除不必要的注释,并压缩 js 文件;
将不进行DOM操作或CSS样式修改的 JavaScript 标记上 sync 或者 defer异步引入;
使用媒体查询属性:将大的CSS文件拆分成多个不同用途的 CSS 文件,只有在特定的场景下才会加载特定的 CSS 文件。
可以通过浏览器调试工具的Network面板中的DOMContentLoaded查看最后生成DOM树所需的时间;


7.样式计算

8.布局阶段
9.分层

10.图层绘制

渲染进程中的合成线程部分

11.切分图块
21、合成线程将图层切分成大小固定的图块(256x256或者512x512)然后优先绘制靠近视口的图块,这样就可以大大加速页面的显示速度;

Ⅳ.GPU进程
12.栅格化操作

Ⅴ.浏览器主进程
13.合成与显示
注意了:合成的过程是在渲染进程的合成线程中完成的,不会影响到渲染进程的主线程执行;
到这里,经过这一系列的阶段,编写好的HTML、CSS、JavaScript等文件,经过浏览器就会显示出漂亮的页面了。

