53

[译] Google 图解:输入 URL 按下 “Enter”,Chrome 干了什么?

 5 years ago
source link: https://mp.weixin.qq.com/s/mTNRBiARF3uvmtcY2MMrbg?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
N7zqArF.jpg!web

文 | Mariko Kosaka

译 | 承香墨影

Chrome 算是程序员的标配了,从全球的市场份额来看,它在全球市场的份额已经超过 60%。

在 Chrome 10 周年之际,官方发布了一个系列文章,用图解的方式,很清晰的讲解了现代浏览器的运行原理。

本文是该系列的第二篇,为了便于阅读,我做了简单修改和注释,建议顺序阅读:

  1. 现代浏览器多进程架构(Chrome 举例)

老规矩,觉得本文有帮助,就点赞、留言或者转发分享吧。你喜欢总要让我知道吧!

导航的背后,发生了什么?

这是关于 Chrome 内部原理系列文章中的第 2 篇。在上一篇文章中,我们研究了不同的 进程和线程中,如何处理浏览器的不同功能 。在这篇文章中,我们深入研究了每个进程和线程如何进行通信以及最终显示网站。

让我们看一个最常见的操作:你在浏览器中输入 URL,然后浏览器从网络获取数据,并显示页面。在这篇文章中,我们将重点讲解用户请求网站,以及浏览器如何呈现网页的部分,这个操作也被称为 导航

从浏览器进程开始

正如我们在第 1 部分中所述: CPU,GPU,内存和多进程架构 ,选项卡外部的所有内容,都由浏览器进程来处理。

浏览器进程具有诸如用来绘制浏览器按钮和输入文本的 UI 线程;处理网络堆栈以及从互联网接受数据的网络线程;控制对文件访问的存储线程等等。例如,当你在地址栏中输入 URL 时,输入的这个动作,将有浏览器进程的 UI 线程处理

uUjuEfQ.jpg!web

一次简单的导航

1. 处理输入

当用户开始输入地址栏时,UI 线程首先会去判断 “这是搜索查询还是 URL?”

在 Chrome 中,地址栏同时具备搜索查询的功能,因此 UI 线程需要解析并确定是将请求发送到搜索引擎,还是发送到待请求的网站。

my6V32Y.jpg!web

2. 开始导航

当用户点击 “Enter” 时,UI 线程启动网络请求,以获取站点内容。加载中状态显示在选项卡的左边,并且网络线程通过适当的协议,如 DNS 查找和 TLS 为请求建立连接。

jYJnEf6.jpg!web

此时,网络线程可以接收并处理 HTTP 301 这样的服务器重定向,在这种情况下,网络线程与处理服务器重定向请求的 UI 线程通信,之后将启动另一个 URL 请求。

3. 读取 Response

一旦响应体(payload)开始接收,网络线程会在必要时,查看数据流的前几个字节,获取响应报文头。

报文头的 Content-Type 用来说明它是什么类型的数据,但由于它可能丢失或错误,所以在这里还需要通过 MIME 类型嗅探,来进一步判断数据类型。这其实是一个很复杂的逻辑,你可以通过阅读源码,以了解不同的浏览器如何处理 Content-Type/Payload。

NJN7ZjE.jpg!web

如果判断是 HTML 文件,那么下一步就是将数据,传递给渲染器进程,但如果它是 zip 文件或其他文件,则表示这是下载请求,因此需要将数据传递给下载管理器。

jyyQjaJ.jpg!web

网络线程会检查响应数据是否是来自 Safe Browsing(安全站点)的 HTML。如果域或响应数据与已知的恶意网站相匹配,则网络线程会发出警告,并显示警告页面。此外,还可能会触发 CORB(Cross Origin Read block)检查,用来确保敏感的跨站点数据无法进入渲染器进程。

需要注意,CORB 发生在 subDownloads 阶段,但是不会发生在顶级导航中。在顶级导航中,会创建一个安全上下文,而浏览器会决定那个渲染器应该处理它,因此,在这种情况下,CORB 是不会执行的。

4. 查找渲染器进程

完成所有的检查,并且当网络线程确定浏览器会导航到请求的站点时,网络线程将通知 UI 线程,数据已经准备就绪。然后,UI 线程通知渲染器进程,进行网页的渲染。

faM3EbM.jpg!web

网络请求是一个耗时操作,这中间可能需要几百毫秒的才能得到响应,因此会对此过程进行加速优化。

当 UI 线程在步骤 2 时,向网络线程发送 URL 请求,浏览器已经能确定他们正在导航的站点。UI 线程尝试与网络请求并行执行,主动查找复用或启动渲染器进程。这样如果一切顺利,则当网络线程开始接收数据时,渲染器进程已处于待用状态。如果导航重定向的 URL 跨站点了,则可能不会使用此备用进程,在这种情况下就需要其他进程来处理了。

5. 提交导航

现在数据和渲染器进程已经准备就绪,为了提交导航,IPC 将从浏览器进程发送一个数据流到渲染器进程。因为此处传递的是一个数据流,渲染器进程可以继续从数据流中接收 HTML 数据。一旦浏览器进程监听到渲染器进程中已经确认提交,一次导航就算完成了,接下来就是文档加载阶段。

此时,地址栏会更新,安全锁(HTTPS证书安全)和站点设置 UI 会显示新页面的站点信息。选项卡的历史记录将更新,因此后退/前进按钮将允许操作之前的浏览器历史。同时会将历史记录存储在磁盘上,以确保关闭选项卡或窗口后,依然可以浏览历史以及还原窗口。

r2Uneau.jpg!web

额外步骤:初始加载完成

提交导航后,渲染器进程继续加载资源,并显示页面。我们将在下一篇文章中详细介绍该阶段的情况。

一旦渲染器进程 “完成” 渲染,它就会通过 IPC 将消息通知回浏览器进程(这是在所有页面中的 onload 事件都触发之后执行的)。此时,UI 线程会隐藏选项卡上的加载进度图标。

这里的 “完成” 之所以加引号,因为客户端 JavaScript 仍然可以加载额外的资源,并在此之后呈现新的视图。

biU7FjM.jpg!web

导航到其他站点

简单的导航,到这里就算完成了。但是如果用户再次将不同的 URL 放到地址栏会发生什么?

浏览器进程会通过相同的步骤,导航到不同的站点。但在此之前,它需要检查当前显示的网站是否注册了 beforeunload 事件。

当你尝试新导航或关闭选项卡时, beforeunload 可以触发显示 “离开这个网站吗?” 这个弹窗,用以提示用户。选项卡内的所有内容,包括 JavaScript 代码都是由渲染器进程处理,因此浏览器进程必须在新导航请求发起时,检查当前的渲染器进程。

注意:不要无条件的添加 beforeunload ,它会产生更多的延迟,应该仅在需要时才监听此事件。例如,警告用户,他们可能会丢失在页面上输入的数据。

Ar26nyZ.jpg!web

如果导航是从渲染器进程发起的,例如用户点击超链接或 JavaScript 代码执行 window.location="https://newsite.com" ,则渲染器进程首先检查 beforeunload 。然后,它将执行浏览器进程启动导航相同的过程,唯一的区别,是导航请求是从渲染器进程启动到浏览器进程。

当新导航进行到与当前渲染的网站不同的网站时,会调用单独的渲染进程来处理新导航,同时保持当前渲染进程用于处理类似 unload 事件。更多信息,可以参阅页面生命周期概览以及如何使用 Page Lifecycle API 。

ZrqQNjY.jpg!web

在上图中,浏览器进程到渲染器进程,有两次 IPC,用来通知渲染新页面并通知旧渲染器进程 Unload。

Service Worker 的情况下

最近在导航过程中,引入了 Service Worker(服务工作线程) 。Service Worker 是浏览器独立于网页运行的服务脚本,它允许 Web 开发人员,更好地控制本地缓存内容,以及必要时从网络获取新数据。如果将 Service Worker 设置为从缓存加载页面,则无需从网络请求数据。

f22ay2e.jpg!web

需要注意,Service Worker 是在渲染器进程中运行 JavaScript 代码,但是当导航请求发起时,浏览器进程如何知道该站点有 Service Worker 呢?

注册 Service Worker 时,将保留 Service Worker 的范围引用。当导航发生时,网络线程根据注册的 Service Worker 范围检查域,如果为该 URL 注册过 Service Worker,则 UI 线程找到渲染器进程,并执行 Service Worker 的逻辑代码。 Service Worker 可以直接从缓存中加载数据,而无需通过网络获取数据,如果在缓存中没有查到数据,再通过网络请求获取数据。

vy2EfeF.jpg!web

如上图,浏览器进程中的 UI 线程,启动渲染器进程来处理 Service Worker,除此之外,还有可能工作线程会从网络请求数据。

导航预加载

可以预想到,如果 Service Worker 最终需要从网络获取数据,则浏览器进程和渲染器进程之间的通信,可能会导致延迟。 导航预加载 是一种通过与 Service Worker 并行加载资源,来加速此过程的机制。它用 Header 标记这些请求,允许服务器决定为这些请求发送不同的内容。例如,只更新部分数据而不是完整文件。

qQfAVzF.jpg!web

小结

在本篇文章中,我们研究了在导航的过程中,执行的流程以及响应头和客户端 JavaScript 等 Web 应用程序的代码,如何与浏览器进行交互。了解了浏览器通过网络获取数据的步骤,可以更容易地理解为什么开发导航预加载等 API。

在下一篇文章中,我们将深入探讨浏览器如何处理 HTML/CSS/JavaScript 并呈现在页面上。

如果本文有帮助,留言、点赞和转发,是最大的支持,谢谢!

原文地址:

https://developers.google.com/web/updates/2018/09/inside-browser-part2

参考阅读:

MIME Type:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types

SafeBorwsing:https://safebrowsing.google.com/

CORB:https://www.chromium.org/Home/chromium-security/corb-for-developers

页面生命周期:https://developers.google.com/web/updates/2018/07/page-lifecycle-api#overview_of_page_lifecycle_states_and_events

Page Lifecycle API:https://developers.google.com/web/updates/2018/07/page-lifecycle-api

Service Worker:https://developers.google.com/web/fundamentals/primers/service-workers/

联机圆桌 」:point_left:推荐我的知识星球,一年 50 个优质问题,上桌联机学习。

公众号后台回复成长『 成长 』,将会得到我准备的学习资料,也能回复『 加群 』,一起学习进步;你还能回复『 提问 』,向我发起提问。

推荐阅读:

图解 Chrome,架构篇 | 利用预处理脚本,管理小程序代码 | 分词,科普及解决方案 | 图解:HTTP 范围请求 | 小程序学习资料 | HTTP 内容编码 | 辅助模式实战 | 辅助模式玩出花样 | 小程序 Flex 布局

n6JFFnR.jpg!web

听说喜欢 留言和分享 的人,会有好运来哦


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK