Appearance
浏览器的导航过程 #
一、处理用户的输入 #
浏览器进程的 UI 线程会判断用户在地址栏的输入是一个搜索查询还是一个 URL。
UI 线程需要解析和决定是将用户的输入发送给搜索引擎,还是导航到用户输入的 URL。
二、开始导航 #
当用户按下 enter 键确认时,UI 线程将发起一个网络调用去获取网站内容, 然后网络线程会为这个请求合适的网络协议比如进行 DNS 查找和建立 TLS 连接。
网络线程可能会收到来自服务端的 HTTP 303 重定向(redirect)请求, 那么网络线程会告诉UI 线程服务端正在重定向到另一个 URL,然后启动另一个 URL request。
三、读取服务端响应 #
当网络线程收到来自服务端的响应内容,首先会查看响应的 Content-Type,然后根据 Content-Type 进行不同的处理。 由 MIME Type Sniffing 完成这里的类型嗅探工作。
如果响应是一个 HTML 文档,那么下一步会将数据传递给渲染进程, 但是如果是一个压缩文件,或者其他类型的文件,那么意味着这是一个下载请求,会将响应数据传递给下载管理器(Download manager)进行处理。
如果域(domain)和响应数据和 SafeBrowsing 已知的恶意网站相匹配,那么网络线程会展示一个警告的页面给用户。
四、寻找渲染进程 #
一旦所有的检查工作都完成了,网络线程认为浏览器可以导航到请求的网站了, 网络线程就会告诉 UI 线程数据准备好了,UI 线程就会寻找一个渲染进程去渲染这个页面。
网络请求获取响应会有一定的时延,因此需要进行优化这个过程,当 UI 进程 向网络线程 发送一个 request 时, 已经知道了要导航到哪一个 URL。因此 UI 进程 可以在这个时候尝试主动查找或者启动一个渲染进程。 这样的话,当网络线程接收到数据时,渲染进程就已经处于待机状态了。
五、提交导航 #
当数据和渲染进程准备就绪时,浏览器进程发送一个 IPC 到渲染进程去提交导航, 它还将传递数据流,以便渲染进程可以继续接收 HTML 数据信息。
当浏览器进程接收到渲染进程发送的确认信息,导航就完成了,进入到了文档加载阶段。
在文档加载阶段,地址栏将会更新,安全指示器和站点设置的 UI 反映了新页面的站点信息,比如说该站点使用了 https 证书,就会展示一个锁的图标。 同时,该 Tab 页的 session history 也会更新,这样的话,前进和后退按钮处于这个 Tab 页时可以穿过这个站点。 Session history 会存储在磁盘中, 以便于关闭选项卡和窗口后,可以从磁盘中恢复这些信息。
初始加载完成 #
一旦导航 commit 完成,渲染进程开始加载资源和渲染页面, 一旦渲染进程“完成”渲染,并且在所有页面上的 frames 触发和执行完了所有的 onload 事件之后, 渲染进程就会发送一个 IPC 告诉 browser process。
之所以说“完成”,是因为客户端的 JavaScript 仍然可以加载额外的资源和渲染视图。
导航到不同的网站 #
如果用户再次在地址栏输入一个新的 URL,那么浏览器可以通过同样的步骤导航到新的网站。 不过在此之前,网站可以触发一个 beforeunload 事件,我们可以在一个填写表单的网站上监听该事件,以提醒用户“离开该页面,已经填写的数据将会丢失”。
当新导航的站点与当前渲染的站点不同时,一个独立的渲染进程开始处理新的导航站点,旧的渲染进程则保留处理事件,比如 unload 事件。
渲染进程触发的导航 #
比如 JavaScript 运行 window.location = "https://newsite.com" 或者用户单击了一个超链接。 渲染进程首先检查 beforeunload 的事件处理器,然后由浏览器进程经过同样的过程开始这次导航。 唯一的不同之处在于,这次导航请求是由渲染进程抛给浏览器进程进行处理的。
Service Worker #
Service Worker 是在你的应用程序代码中编写网络代理(network proxy)的一种方法,允许开发者对本地缓存的内容以及何时从网络获取新数据有更多的控制。 如果 Service Worker 设置从缓存加载页面,那么无需从网络请求数据。
重点部分是 service worker 是运行在渲染进程中的 JavaScript 代码, 但是当导航请求传入的时候,浏览器进程如何知道这个站点有一个 service worker呢?
当一个 service worker 被注册,这个 service worker 的 scope 作为一个引用(reference)保存。 当一个导航发生时,网络线程会检查域(domain)注册的 service worker scopes,如果有一个 service worker 为那个 URL进行了注册, UI 线程会查找一个渲染进程去执行 service worker 的代码。这个 service worker 也许从缓存中去加载数据,而不需要从网络请求数据, 也许会从网络请求新的资源。
导航预加载 #
如果 service worker 最终决定从网络请求数据,浏览器进程和渲染进程之间的往返可能会导致延迟。
导航预加载是一种通过在 service worker 启动时并行加载数据来加速此过程的机制, 它基于 header 标记这些请求,允许服务器绝对为这些请求发送不同的内容,例如只更新数据而不是完整的文档。
参考资料 #
Chrome Developers - Inside look at modern web browser (part 2)