总结
从多个进程的角度,解释从浏览器接受到 URL 到页面显示中间的一些过程。重点主要是导航的过程,包括以地址栏输入 URL 的方式打开新的页面,或者从一个页面的链接跳转到另一个页面。
文章的特点是说到了多个进程之间的通信和协作。主要是网络进程,浏览器进程,渲染进程之间的通信。在 Google 官方的文档中,分为浏览器进程,和渲染进程。其中浏览器进程包括 UI 线程,存储线程,网络线程。
导航流程
-
处理输入(浏览器进程->UI 线程)
用户在地址栏输入时,UI 线程会判断所输入的字符串是查询搜索还是 URL?如果是查询搜索则将查询内容发送到默认搜索引擎。如果是 URL 则发送到 URL 对应的网站。
-
向 URL 发送请求(浏览器进程->网络线程)
-
查找缓存
网络进程会根据缓存机制查找缓存,如果缓存不可用,则需要发送请求进入网络请求流程。缓存过期,Last-Modified/If-Last-Modified,Etag/If-None-Modified,Expire,Cache-Control。200,304。
-
DNS 解析
依次从浏览器 DNS 缓存,到本机的 host 文件,再发送 DNS 查询。递归查询。从根域名服务器遍历。 -
TCP 连接
三次握手:SYN, SYN-ACK, ACK,四次挥手,传输控制 -
TLS 连接
认证加密,重点是认证中心是可信的,认证中心将信任通过证书授予到某个 web 服务器。客户端通过认证中心的公钥解密证书,确认证书可信从而确认与之一同被发送的 web 服务器的公钥可信。再通该可信的公钥加密密钥,发送给当前连接中与之通信的 web 服务器,如果对方是同一个 web 服务器,那么就应该拥有对应的私钥,就能够解密数据从而取出密钥。 -
数据传输
发送请求行,请求头,请求体。
-
-
阅读响应(浏览器进程->网络线程)
- 数据类型
一旦收到响应体数据开始,网络线程根据响应头数据分析响应体的数据类型,并且更具不同的数据类型决定下一步。如果响应是 HTML 文件类型,则下一步的目的就是将数据传递给渲染进程,如果是 zip 文件类型或者其他文件请求,则需要将数据传递给下载管理器。 - 重定向
如果响应头中的状态码为 301 或 302,则需要重定向,重定向的地址为响应头中的 Location 字段。然后重新发起新的请求。 - 安全检查
这也是安全中断检测发生的地方。如果域名和响应数据被检测为恶意网站,则网络线程会发出警报以显示警告页面。此外 Cross Origin Read Block 检查的发生,以确保敏感的跨站点数据不会进入渲染过程。
- 数据类型
-
查找渲染进程(浏览器进程->网络线程 到 浏览器进程->UI 线程 到 渲染进程)
完成安全检查之后,网络线程确信浏览器应该导航到请求的站点,网络线程通知 UI 线程数据已经准备就绪,然后 UI 线程找到一个渲染进程对网页进行渲染。
由于网络请求可能需要几百毫秒才能得到响应,所以 UI 线程可以在网络线程收到响应数据之前尝试主动查找或启动与网络线程发送请求并行的渲染进程。当网络线程接受数据时,渲染进程已经准备就绪了。
-
提交导航(浏览器线程 -> 渲染线程)
网络线程的响应数据和渲染进程都准备就绪时,浏览器进程将通过 IPC 通知渲染进程“提交导航”,此外浏览器进程还会将数据流传递给渲染进程,以便渲染进程可以继续接收响应数据。
-
确认提交(渲染线程 -> 浏览器线程)
渲染线程接受完响应数据之后,通过 IPC 向浏览器进程发送“确认提交”的消息。此时导航阶段就完成了,进入文档加载阶段。
浏览器进程的 UI 线程会更新地址栏,安全指示器,和站点设置的 UI以反映新页面的站点信息。选项卡的会话历史记录也将更新,会话历史记录存储在磁盘上。
提交文档阶段
浏览器进程将网络进程接收到的 HTML 数据提交给渲染进程:
- 网络进程下载并读取响应头数据。
- 网络进程响应头数据下载并读取完毕后通知并将响应头数据发送给浏览器进程。
- 浏览器进程通知渲染进程“提交文档”并将渲染头数据转发给渲染进程。
- 渲染进程收到“提交文档”的消息以及响应头数据后,与网络进程建立数据传输的“管道”,直接从网络进程接收剩下的响应体数据。
- 响应体数据传输完毕之后,渲染进程发送“确认提交”的消息给浏览器进程。
- 浏览器进程收到“确认提交”的消息后,会更新浏览器界面状态,包括安全状态、地址栏的 URL、前进后退的历史状态、并更新页面。
渲染阶段
Content-Type 决定浏览器对响应的处理方式,可能是转到下载管理器,也可能是当作网页处理(text/HTML)。
共用渲染进程
多个网页可能会公用一个渲染进程,取决于它们所属的站点和打开的方式:如果从 A 页面打开 B 页面,且 A 和 B 属于同一站点,那么 B 页面会 复用 A 页面的渲染进程,否则新打开的页面会使用单独的渲染进程。