04 导航流程:从输入url到打开页面发生了什么
看到一篇还不错的更底层的讲解博客:从 URL 输入到页面展现到底发生了什么?
导航流程:用户发出URL请求到页面开始解析的这个过程
从输入URL到页面展示流程:
1、用户输入
浏览器进程中的 UI 线程
对输入内容做区分,并生成对应 URL
:
- 如果查询关键字是
url
– 根据规则,把这段内容加上协议,合成为完整的URL
- 如果查询关键字是
搜索内容
– 使用浏览器默认的搜索引擎,来合成新的带搜索关键字的URL
## 2、URL请求过程 浏览器进程 - UI 线程 会通过进程间通信(IPC)把 URL 请求发送至网络进程 — > 此时浏览器标签页的标题会出现 “加载中” 的图标
URL请求流程:
1、网络进程
会查找 本地缓存 是否缓存了该资源
- 有,直接返回资源
- 没有缓存,进入网络请求流程
2、第一步是要进行 DNS解析,获取 ip 地址
- 如果请求协议是HTTPS,那么还需要建立
TLS
连接
3、利用IP地址和服务器建立 TCP连接
4、浏览器端会构建请求行、请求头等信息,并把和 该域名相关 的 Cookie
等数据附加到请求头中,然后 向服务器发送构建好的请求信息
5、服务器会根据请求信息 生成响应数据,并发给 网络进程
7、网络进程会解析响应头
- 返回的状态码是
301
或者302
– 重定向,网络进程
会从响应头的Location
字段里面读取重定向的地址 —> 网络进程会通知 UI线程 需要重定向 —> 然后以新的地址开始请求资源,一切又重头开始了 - 状态码是200,继续解析
8、对响应数据类型处理,网络进程
通过响应头中的 Content-Type
区分响应体中的数据类型:
-
如果属性值为
text/html
- HTML格式,继续进行导航流程,浏览器进程需要 准备渲染进程 -
如果属性值为
application/octet-stream
- 字节流类型 –> 通常情况下,浏览器会按照下载类型来处理该请求 —> 该请求会被提交给浏览器的下载管理器,同时该URL请求的 导航流程就此结束3、准备渲染进程
渲染进程策略:
- 默认情况下,
Chrome
会为 每个页面分配一个渲染进程 - 新页面和当前页面属于同一站点,那么新页面会复用父页面的渲染进程 –> 多个页面直接运行在同一个渲染进程 中【process-per-site-instance策略】
注意:同一站点(same-site)要求 —> 根域名(例如,geekbang.org)加上协议(例如,https:// 或者http://),还包含了该根域名下的所有子域名和不同的端口,如下所示:
https://time.geekbang.org
https://www.geekbang.org
https://www.geekbang.org:8080
注意:浏览器进程把渲染进程准备好之后,还不能立即进入文档解析状态,因为此时的文档数据还在 网络进程 中,并没有提交给渲染进程,所以下一步就进入了提交文档阶段
4、提交文档
文档:指URL请求的响应体数据 准备好渲染进程之后,在三个进程之间有个“提交文档”的消息在处理,处理流程如下:
1⃣️:浏览器进程 向 渲染进程 发出“提交文档”的消息 2⃣️:渲染进程接 收到“提交文档”的消息后,会和 网络进程 建立传输数据的“管道”,边传边解析 3⃣️:等文档数据传输完成之后,渲染进程 会返回“确认提交”的消息给 浏览器进程 4⃣️:浏览器进程 在收到“确认提交”的消息后,会更新浏览器界面状态,包括了 安全状态、地址栏的URL、前进后退的历史状态(硬盘内存),并更新Web页面,即下图标注的四个内容
所以:在浏览器的地址栏里面输入了一个地址后,之前的页面没有立马消失,而是要加载一会儿才会更新页面
5、渲染阶段
在这个阶段进行页面解析和子资源(iframe)加载,完成后 渲染进程 会发送一个消息给 浏览器进程 —> 也就是 onLoad
事件触发后发送 —>浏览器接收到消息后,UI线程会停止标签图标上的加载动画
但这里”结束”并不意味着所有的加载工作都结束了,因为可能还有 JavaScript 在加载额外的资源或者渲染新的视图。
6、访问不同的站点
1-5 是一次完整的普通访问,当我们输入另外的地址时,浏览器会重复上面的过程。
但是 在开始新的访问前,会确认当前的站点是否关心 beforeunload
事件。由于所有的包括渲染、运行 Javascript 的工作都发生在渲染进程中,浏览器进程需要在 新的访问开始前 与渲染进程确认当前的站点是否关心unload
-
补充:
beforeunload
事件可以提醒用户 是否要访问新的站点或者关闭页签,如果用户拒绝则新的访问或关闭会被阻止。 -
案例:
如果一次访问是从一个渲染进程中发起的,例如用户点击一个链接或者运行 JavaScript 代码
location = 'http://newsite.com'
时,渲染进程首先检查beforeunload
。然后再执行和浏览器进程初始化访问同样的步骤,只不过区别在于这样的访问请求是 由渲染进程向浏览器进程发起的