本文是根据Mariko Kosaka在谷歌开发者网站上的系列文章https://developer.chrome.com/blog/inside-browser-part2/ 翻译而来,共有四篇,该篇是第二篇。对于其中一些直译出来不太好理解的句子,笔者做了加工处理和提炼。

在导航中发生了什么

在上一篇文章中,我们了解到了不同的进程和线程如何处理浏览器中的各个部分。在这篇文章中,我们将更深入探讨各个进程和线程如何通信以展示出一个网页来。

让我们来看一个简单的浏览网页的场景:当你输入URL后,浏览器从因特网中获取数据并把页面展示出来。在本文中,我们将重点关注用户请求站点和浏览器准备呈现页面的部分——也就是导航。

从浏览器进程开始

如我们在第一篇文章中https://www.cnblogs.com/geek1116/p/16419720.html所述,tab页之外的所有内容都是由浏览器进程处理的。浏览器进程具有诸如渲染按钮和输入框的UI线程、处理网络栈以从因特网中接收数据的网络线程,以及控制文件等内容访问的存储线程;当你向地址栏中输入URL时,就是由浏览器进程的UI线程来处理你的输入。

顶部的浏览器UI,底部是包含UI、网络和存储线程的浏览器进程

一个简单的导航

步骤1:处理输入

当用户在地址栏中输入的时候,UI线程首先需要考虑的是:“输入内容是一个搜索请求还是URL呢?”。在Chrome中,地址栏同时也是搜索输入域,因此UI线程需要解析并决定将输入内容发送到搜索引擎还是你想要请求的站点。

UI线程在判断输入内容是一个搜索请求还是URL

步骤2:开始导航

当用户敲击回车键后,UI线程发起一个网络调用来获取站点内容。在tab栏的一角会显示加载效果,网络线程会查找合适的协议做接下来的事 例如根据DNS查找域名、为请求建立TSL连接。

UI线程通知网络线程导航至mysite.com

此时,网络线程可能会收到HTTP 301之类的服务重定向标头(header)。这种情况下,网络线程会告知UI线程该服务需要请求重定向。接着便会发起另一个URL请求。

步骤3:读取响应

一旦响应主体(有效负载)开始进入,网络线程会在有必要时检查流(stream)的前面几个字节。这是因为:响应头部的Content-Type字段会告知数据的类型,但它可能会丢失或者出错,所以在这里进行MIME 嗅探。如chromium源码注释中所说,这是一项“棘手的业务”;你可以阅读该处的注释并看到不同浏览器是如何处理content-type/payload的。

如果响应是一个HTML类型文件,则会将该数据传递给渲染进程;而如果是一个zip或其他类型文件的话,意味着这是一个下载请求所以需要将该数据传递给下载管理器。

网络线程检查响应数据是否是来自安全站点的HTML文件

↑这里也是进行安全浏览检查的地方。如果响应数据和对应的域(domain)与已知的恶意站点相匹配的话,网络线程会发出警告页面。此外,还会做的一项检查CROB——跨域源读阻止(注意是CROB不是CROS),确保跨域的敏感数据不会到达渲染进程。

步骤4:查找渲染进程

当所有的检查完成并且网络线程确信浏览器应该导航至请求站点后,就会告知UI线程数据已经准备就绪。然后UI线程找出一个渲染进程来进行网页的渲染:

由于网络请求可能需要花费数百毫秒之久来等待响应返回,所以一项加速此过程的优化手段应运而生:当UI线程在上述步骤2中向网络线程发送URL请求时,是已经知道它所要导航的站点的,此时它会在网络请求期间并行地查找或启动一个渲染进程。这样一来,如果一切按预期进行,当网络线程的数据到达时,渲染进程就已经处于就绪状态了。如果导航发生重定向是且跨站点的话,则可能不会使用该就绪进程,这种情况下需要使用另外的进程了。

步骤5:提交导航

现在数据和渲染进程都已经准备好了,浏览器进程会向渲染进程发送一个IPC(第一篇文章中提到的进程间通讯手段)来提交导航。该IPC也会被用来传递数据流(stream)以让渲染进程可以持续接收HTML数据。当浏览器进程收到渲染进程中对导航提交的确认,本次导航就结束了,接着开始HTML文档的加载阶段。

这时候地址栏就被更新了,安全指示器和站点设置UI(地址栏最左侧的图标)上会反映出新页面的站点信息。该tab页的会话历史将会被更新——因此可以让顶部的后退/前进按钮在曾经导航过的站点间逐次跳转。为了能够让你在关闭tab页/窗口后恢复tab页/会话,会话历史会被储存到磁盘上。

浏览器进程和渲染进程之间的IPC,请求渲染页面

额外步骤:初始化加载完成

导航提交后,渲染进程会继续加载资源和渲染页面。我们会在下一篇文章中详细此阶段完成的内容。当渲染进程“完成”渲染之后,会返回IPC给浏览器进程(这发生在页面以及所有内嵌iframe的onload事件触发并执行完之后)。此时,UI线程会停止tab标签旁边的加载效果。

上面一段中的“完成”字样我特意用双引号括起来,这并不代表着真正的完成,因为在此之后Javascript仍然可以加载其他资源并渲染新的视图。

从渲染进程到浏览器进程的IPC来通知页面“已加载”

导航到其他站点

这个简单的导航过程就完成了!但是如果用户又在地址栏中输入一个不同URL的话会发生什么呢?好吧,浏览器进程将通过相同的步骤来达到新的站点。但在此之前,它需要检查下当前渲染的页面是否需要关注beforeunload事件。

beforeunload可以在你试图导航至别处或关闭tab页时创建“离开此站点?”的警告。tab中的所有东西包括你的Javascript代码都是渲染进程处理的,所以浏览器进程必须在新的导航请求到来时检查当前的渲染进程。

从浏览器进程到渲染进程的IPC,告知即将导航到新站点

如果导航是从渲染进程启动的(例如用户点击了一个链接或者客户端的Javascript运行了window.location="https://newsite.com"),渲染进程会首先检查beforeunload处理器。之后所经历的过程就和浏览器进程启动导航的一样了。唯一的区别在于导航请求是从渲染进程到浏览器进程中的。

当新导航指向的站点不同于当前渲染的站点时,会调用另一个单独的渲染进程来处理新导航,而当前的渲染进程会被保留以处理诸如unload等事件。更多详情请参见页面生命周期状态概述以及如何使用页面生命周期API

从浏览器进程到新渲染进程告知渲染页面和到旧渲染进程卸载的两个IPC

Service Worker

这个导航过程最近新引入的一个变化是service workder。service workder是一种在应用程序代码中编写网络代理的方法;允许Web开发人员更好地控制本地缓存的内容以及何时从网络获取新数据。如果service workder设置为从缓存中加载页面,则无需向网络请求数据。

需要记住的一个重点是,service workder是运行在渲染进程中的Javascript代码。但是当导航请求到来的时候,浏览器进程如何知道该站点有service workder呢?

当注册了一个service workder后,该service workder的作用域会被作为一个引用保存(你可以在这篇Service Worker生命周期中了解过于作用域的更多信息)。当一个新导航发生时,网络线程根据已注册的service worker作用域来检查新站点的域(domain),如果该域的URL有对应注册的service worker,UI线程会找到一个渲染进程以运行service worker代码。service worker能够从缓存中加载数据,这样就不用从网络上请求数据;或者它也可以从选择从网络上请求资源。

浏览器进程中的网络线程在查到service worker的作用域

浏览器进程中的UI线程启动了一个渲染进程来处理service worker;然后渲染进程中的worker线程从网络请求数据

导航预加载

你可以看到如果service worker最终决定从网络请求数据的话,在浏览器进程和渲染进程之间的这种往返会造成延迟。Navigation Preload是一种通过在service worker时并行加载资源来加速这一过程的机制。它会给这些请求的header中做标记以表示这是由Navigation Preload机制发出的请求,然后服务器可以决定对这些请求返回不同的内容;例如只更新部分数据而不是返回整个HTML文档。

浏览器进程中的UI线程在启动一个渲染进程来执行service worker的同时并行地发出网络请求

总结

在这篇文章中,我们研究了导航期间发生的事情以及你的web应用程序(例如响应header和客户端javascript)是如何与浏览器交互的。了解了浏览器从网络请求数据所经历的步骤,让我们更加明白了为什么要开发出类似Navigation Preload的这些APIs。在下篇文章,我们将深入探讨浏览器是如何解析我们的HTML/CSS/Javascript来渲染页面的。

[译]深入了解现代web浏览器(二)的更多相关文章

  1. [译]36 Days of Web Testing(二)

    Day 7: Http 和 Https Why? 当在网络上传输一些私人,敏感信息时,应该采用加密的手段来保证这些信息在传输的过程中不被侦测到.Https协议正是这种实现机制. Https是一种广泛使 ...

  2. 第十一章:WEB浏览器中的javascript

    客户端javascript涵盖在本系列的第二部分第10章,主要讲解javascript是如何在web浏览器中实现的,这些章节介绍了大量的脚本宿主对象,这些对象可以表示浏览器窗口.文档树的内容.这些章节 ...

  3. [C# 网络编程系列]专题四:自定义Web浏览器

    转自:http://www.cnblogs.com/zhili/archive/2012/08/24/WebBrowser.html 前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发 ...

  4. SeaJS:一个适用于 Web 浏览器端的模块加载器

    什么是SeaJS?SeaJS是一款适用于Web浏览器端的模块加载器,它同时又与Node兼容.在SeaJS的世界里,一个文件就是一个模块,所有模块都遵循CMD(Common Module Definit ...

  5. 006-优化web请求二-应用缓存、异步调用【Future、ListenableFuture、CompletableFuture】、ETag、WebSocket【SockJS、Stomp】

    四.应用缓存 使用spring应用缓存.使用方式:使用@EnableCache注解激活Spring的缓存功能,需要创建一个CacheManager来处理缓存.如使用一个内存缓存示例 package c ...

  6. 转:【专题四】自定义Web浏览器

    前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发出请求的正是本专题要介绍的Web浏览器,本专题通过简单自定义一个Web浏览器来简单介绍浏览器的工作原理,以及帮助一些初学者揭开浏览器这 ...

  7. WEB入门二 表格和表单

    学习内容 Ø        表格的作用和制作 Ø        表单的制作 能力目标 Ø        掌握表格的创建 Ø        掌握设置表格的常用属性: Ø        理解表单的作用 Ø ...

  8. C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志

    C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...

  9. 专题四:自定义Web浏览器

    前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发出请求的正是本专题要介绍的Web浏览器,本专题通过简单自定义一个Web浏览器来简单介绍浏览器的工作原理,以及帮助一些初学者揭开浏览器这 ...

  10. 前端Web浏览器基于Flash如何实时播放监控视频画面(前言)之流程介绍

    [关键字:前端浏览器如何播放RTSP流画面.前端浏览器如何播放RTMP流画面] 本片文章只是起到抛砖引玉的作用,能从头到尾走通就行,并不做深入研究.为了让文章通俗易懂,尽量使用白话描述. 考虑到视频延 ...

随机推荐

  1. Python从0到1丨图像增强及运算:形态学开运算、闭运算和梯度运算

    摘要:本文主要介绍图像形态学处理,详细讲解了图像开运算.闭运算和梯度运算.数学形态学是一种应用于图像处理和模式识别领域的新方法,其基本思想是用具有一定形态的结构元素去量度和提取图像中对应形状以达到对图 ...

  2. 如何用 DataTester 设计并创建可视化实验

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 设计一个可视化实验 确定实验目标:(示例)通过修改页面的「免费试用」按钮背景颜色,提高免费试用按钮的转化率. 确定 ...

  3. Runnable接口的 run() 方法和start()方法

    1.start()方法来启动线程,真正实现了多线程运行.这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码:通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就 ...

  4. 如何使用Java在Excel中添加动态数组公式?

    本文由葡萄城技术团队发布.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 动态数组公式是 Excel 引入的一项重要功能,它将 Excel 分为两种风 ...

  5. 用 Python 开发了一个 PDF 抽取Excel表格的小工具

    大家好哇 从 PDF 里 copy 表格时,粘贴出来后格式都是错乱的.这麻烦事交给 Python 再合适不过里,我开发了一个从 PDF 抽取表格另存为 Excel 文件的应用,我把它部到 huggin ...

  6. C++正则表达式的初步使用

    正则表达式(Regular Expressions),又被称为regex.regexp 或 RE,是一种十分简便.灵活的文本处理工具.它可以用来精确地找出某文本中匹配某种指定规则的内容.从C++11开 ...

  7. Codeforces Round #719 (Div. 3) A~E题解

    51鸽了几天,有几场比赛的题解还没发布,今天晚上会补上的 1520A. Do Not Be Distracted! 问题分析 模拟,如果存在已经出现的连续字母段则输出NO using ll = lon ...

  8. C#开源跨平台的多功能Steam工具箱&GitHub加速神器

    前言 作为一个程序员你是否会经常会遇到GitHub无法访问(如下无法访问图片),或者是访问和下载源码时十分缓慢就像乌龟爬行一般.今天分享一款C#开源的.跨平台的多功能Steam工具箱和GitHub加速 ...

  9. .NET CORE实战项目之CMS 开发篇 思维导图

    导图地址下载: 链接:https://pan.baidu.com/s/1sGiNZI-pc_yueqQiddvImQ 提取码:ql4v -------------------------------- ...

  10. Linux系统CPU异常占用(minerd 、tplink等挖矿进程)

    转载请注明出处: 云服务器ECS(Linux) CPU使用率超过70%,严重时可达到100%,服务器响应越来越慢.  服务器中存在恶意minerd.tplink进程 该进程是服务器被入侵后,被恶意安装 ...