输入url到页面展示这中间发生了什么

这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战

输入url到页面展示这中间发生了什么

我们有了前面的浏览器多进程架构和网络请求的知识,我们开始分析从输入url到页面展示这中间发生了什么?

  • 首先,浏览器进程接收到用户输入的 URL 请求,浏览器进程便将该 URL 转发给网络进程。
  • 然后,在网络进程中发起真正的 URL 请求。
  • 接着网络进程接收到了响应头数据,便解析响应头数据,并将数据转发给浏览器进程。
  • 浏览器进程接收到网络进程的响应头数据之后,发送“提交导航(CommitNavigation)”消息到渲染进程;
  • 渲染进程接收到“提交导航”的消息之后,便开始准备接收 HTML 数据,接收数据的方式是直接和网络进程建立数据管道;
    • 当commitNavigationEnd事件触发,即提交导航流程结束,旧的文档已经被pageHide了
  • 最后渲染进程会向浏览器进程“确认提交”,这是告诉浏览器进程:“已经准备好接受和解析页面数据了”。
  • 浏览器进程接收到渲染进程“提交文档”的消息之后,然后更新浏览器进程中的页面状态, 然后开始解析响应数据, 导航结束。 这时才开始替换, 即通知渲染进程解析文档并更新 Web 页面。
  • 这其中,用户发出 URL 请求到页面开始解析的这个过程,就叫做导航。

在第一步中,浏览器进程接收到用户输入的 URL 请求后,当前页面会被替换成新的页面,不过在进行到浏览器进程将url转发给网络进程之前,浏览器还提供了beforeunload钩子,用户可以在这个钩子内部来取消导航,即使用户没有写这个钩子,那么这个钩子还是会被执行,进行一些清理操作。即在导航之前浏览器线程会触发当前页的卸载事件和收集需要释放内存,这占用了一些时间,但大头是请求新的url时的返回。

当没有beforeunload钩子的时候,或者用户在beforeunload钩子可以进行导航,那么我们会进行到下一个步骤:

什么是提交文档? 下文会说。

接下来,便进入了页面资源请求过程。这时,浏览器进程会通过进程间通信(IPC)把 URL 请求发送至网络进程,网络进程接收到 URL 请求后,会在这里发起真正的 URL 请求流程。

网络进程请求我们上文说的很清楚了

网络进程会查找缓存,有缓存直接用,没缓存发送就dns解析,获取服务器ip地址,如果是https,要建立ssl连接,然后利用ip地址和端口号进行tcp连接,连接建立成功,浏览器会通过http协议构建请求头,请求体,请求行,服务器进行处理,当服务器处理完成之后,返回响应行,响应头,响应体。构建请求、查找缓存、准备 IP 和端口、等待 TCP 队列、建立 TCP 连接、发起 HTTP 请求、服务器处理请求、服务器返回请求和断开连接。

假如服务器返回了200状态码

接下来浏览器要处理响应了,那么浏览器是如何区分响应类型的呢? 比如有些类型是html文件需要渲染到页面上,有些是下载类型需要下载下来,浏览器会使用响应头中的Content-type的值来决定如何处理响应体中的内容。

如果Content-Type 的值是 application/octet-stream,显示数据是字节流类型的,通常情况下,浏览器会按照下载类型来处理该请求。需要注意的是,如果服务器配置 Content-Type 不正确,比如将 text/html 类型配置成 application/octet-stream 类型,那么浏览器可能会曲解文件内容,比如会将一个本来是用来展示的页面,变成了一个下载文件。所以,不同 Content-Type 的后续处理流程也截然不同。如果 Content-Type 字段的值被浏览器判断为下载类型,那么该请求会被提交给浏览器的下载管理器,同时该 URL 请求的导航流程就此结束。但如果是 HTML,那么浏览器则会继续进行导航流程。由于 Chrome 的页面渲染是运行在渲染进程中的,所以接下来就需要准备渲染进程了。

接下来我们要准备渲染进程了

默认情况下,Chrome 会为每个页面分配一个渲染进程,也就是说,每打开一个新页面就会配套创建一个新的渲染进程。但是,也有一些例外,在某些情况下,浏览器会让多个页面直接运行在同一个渲染进程中。

Chrome 的默认策略是,每个标签对应一个渲染进程。但如果从一个页面打开了另一个新页面,而新页面和当前页面属于同一站点的话,那么新页面会复用父页面的渲染进程。官方把这个默认策略叫 process-per-site-instance。

总结来说,打开一个新页面采用的渲染进程策略就是:通常情况下,打开新的页面都会使用单独的渲染进程;如果从 A 页面打开 B 页面,且 A 和 B 都属于同一站点的话,那么 B 页面复用 A 页面的渲染进程;如果是其他情况,浏览器进程则会为 B 创建一个新的渲染进程。渲染进程准备好之后,还不能立即进入文档解析状态,因为此时的文档数据还在网络进程中,并没有提交给渲染进程,所以下一步就进入了提交文档阶段

浏览器进程在收到“确认提交”的消息后,会更新浏览器界面状态

到这里,从用户发出url请求到页面开始解析的这个导航过程就结束了。下面就来到了渲染阶段。

一旦文档被提交(即: 浏览器进程在收到“确认提交”的消息后),渲染进程便开始页面解析和子资源的加载了。

当页面生成完毕,子资源加载完成之后,渲染进程会发送一个消息给浏览器进程,浏览器进程接收到消息后,会停止标签上的加载动画(favio.icon占据的那个位置)

总结

  1. 服务器可以根据响应头来控制浏览器行为,如重定向,setCookie,下载。
  2. 浏览器的导航流程包括从用户发起请求到提交文档给渲染进程的中间所有阶段。

导航流程很重要,他是网络加载流程和渲染流程之间的一座桥梁。如果理解了导航流程,那么就能串联起来整个页面的显示流程。

QA:

<a target="_blank" rel="noopener noreferrer" class="hover" href="https://linkmarket.aliyun.com/hardware_store?spm=a2c3t.11219538.iot-navBar.62.4b5a51e7u2sXtw" data-spm-anchor-id="a2c3t.11219538.iot-navBar.62">硬件商城</a>  
复制代码

使用noopener noreferrer就是告诉浏览器,新打开的子窗口不需要访问父窗口的任何内容,这是为了防止一些钓鱼网站窃取父窗口的信息。 浏览器在打开新页面时,解析到含有noopener noreferrer时,就知道他们不需要共享页面内容,所以这时候浏览器就会让新链接在一个新页面中打开了。

猜你喜欢

转载自juejin.im/post/7032310553959890957