「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战」
选项卡之外的所有内容都由浏览器进程处理。浏览器进程具有诸如绘制浏览器按钮的 UI 线程、处理网络堆栈以从 Internet 接收数据的网络线程、对文件的访问控制的存储线程等线程。当在地址栏中输入 URL 时,由浏览器进程的 UI 线程处理。
地址栏输入
当用户开始在地址栏中输入内容时,UI 线程会判断这是“这是搜索查询还是 URL?”。在 Chrome 中,地址栏也是一个搜索输入框,UI 线程会解析并决定是将输入的内容发送到搜索引擎还是用户请求的站点。
开始导航
当用户点击回车时,UI 线程会发起网络调用以获取站点内容。加载 loading 会显示在选项卡的一角,网络线程会进行 DNS 查找,为请求建立 TLS 连接等等。
服务器返回数据,此时,网络线程可能会收到像 HTTP 301 这样的服务器重定向状态码。在这种情况下,网络线程会与服务器正在请求重定向的 UI 线程通信。然后,将发起另一个 URL 请求。
阅读回复
一旦响应主体(有效负载)开始进入,网络线程会在必要时查看流的前几个字节。响应的 Content-Type 标头会说明它是什么类型的数据。如果响应是一个 HTML 文件,那么下一步就是将数据传递给渲染器进程,但如果它是一个 zip 文件或其他文件,那么这意味着它是一个下载请求,需要将数据传递给下载管理器。
这也是进行安全浏览检查的地方。如果域名和响应数据与已知的恶意站点相匹配,则网络线程会发出警报以显示警告页面。此外, 发生跨源读取检查是为了确保敏感的跨站点数据不会进入渲染器进程。
渲染器进程
一旦完成所有检查并且网络线程确信浏览器导航到了请求的站点,网络线程就会告诉 UI 线程数据已准备好。UI 线程就会找到一个渲染器进程来进行网页的渲染。
由于网络请求可能需要数百毫秒才能得到响应。当 UI 线程在第 2 步向网络线程发送 URL 请求时,它已经知道他们应该导航到哪个站点。UI 线程尝试主动查找或启动与网络请求并行的渲染器进程。这样,如果一切按预期进行,当网络线程接收到数据时,渲染器进程已经处于待机位置。如果导航重定向跨站点,则可能不会使用此备用进程。
提交导航
现在数据和渲染器进程已准备好,浏览器进程向渲染器进程发送 IPC 以提交导航。它还传递数据流,因此渲染器进程可以继续接收 HTML 数据。一旦浏览器进程听到在渲染器进程中发生提交的确认,导航就完成了,文档加载阶段就开始了。
此时,地址栏更新,UI 反映了新页面的站点信息。该选项卡的会话历史记录将被更新,后退/前进按钮将逐步浏览刚刚导航到的站点。同时,会话历史记录存储在磁盘上。
额外步骤:初始加载完成
提交导航后,渲染器进程会继续加载资源并渲染页面。一旦渲染器进程“完成”渲染,它会将 IPC 发送回浏览器进程(这是在 onload页面中的所有帧上触发所有事件并完成执行之后)。此时,UI 线程停止选项卡上的loading。当然,在此之后客户端 JavaScript 仍然可以加载其他资源并呈现新视图。
导航到其他站点
如果用户再次将不同的 URL 放到地址栏,此时,浏览器进程通过相同的步骤导航到不同的站点。但在此之前,它需要检查当前呈现的站点是否有beforeunload事件。
当尝试离开或关闭选项卡时会发出警报。选项卡内的所有内容,包括 JavaScript 代码,都由渲染器进程处理,因此当新的导航请求进来时,浏览器进程必须检查当前的渲染器进程。
如果导航是从渲染器进程启动的(例如用户单击链接或客户端 JavaScript 运行window.location = "https://newsite.com"),则渲染器进程首先检查beforeunload程序。然后,它会经历与浏览器进程启动导航相同的过程。唯一的区别是导航请求是从渲染器进程启动到浏览器进程的。
当新导航指向与当前呈现的站点不同的站点时,会调用一个单独的呈现进程来处理新的导航,而当前的呈现进程会被保留。
Service Worker
浏览器中引入了 service worker。Service Worker 是一种在应用程序代码中编写网络代理的方法;允许 Web 开发人员更好地控制本地缓存的内容以及何时从网络获取新数据。如果 Service Worker 设置为从缓存中加载页面,则无需向网络请求数据。
当导航发生时,网络线程会根据注册的 Service Worker 范围进行检查,如果该 URL 注册了Service Worker,则 UI 线程会找到一个渲染器进程以执行 Service Worker 代码。Service Worker 可以从缓存中加载数据,从而无需从网络请求数据,或者它可以从网络请求新资源。
Navigation Preload
如果 Service Worker 最终决定从网络请求数据,浏览器进程和渲染器进程之间可能会有延迟。 Navigation Preload 是一种通过在 Service Worker 启动时并行加载资源来加速此过程的机制。