原文:https://alistapart.com/articl...最近在国外找了一个系列,专门研究从输入到探索URLtopage交互详细过程,是个干货满满的好素材。作者决定将其分为四篇,删减翻译。只希望能对大家有所帮助。毕竟这是前端必备的知识点,也是容易忽略一些细节的知识点。提前声明,本系列完全由作者翻译。如有翻译不当之处,敬请读者提出改进意见!让我们从第一篇文章开始-《从服务端到客户端》在浏览器可以做任何工作之前,它需要知道它正在访问哪里。有几种方法可以实现访问:在地址栏中键入URL,单击(或点击)页面或其他应用程序中的超链接,或者点击您的收藏夹。在任何一种情况下,都会触发一个动作——导航。导航始终是网页交互的第一步,因为它会触发事件的连锁反应,直到页面加载完毕。初始化请求一旦将URL提供给浏览器进行加载,下面的事情就会在幕后悄悄发生:检查HSTS首先,浏览器需要确定URL是否是明确的HTTP(不安全)。如果是HTTP请求,那么浏览器需要检查域名是否在HSTS列表中(HTTPStrictTransportSecurity-严格安全传输)。此列表包含一个预加载列表和一个您之前访问过的使用HSTS的网站列表,它们存储在浏览器中。如果你请求的以HTTP开头的主机在HSTS列表中,则请求将被强制为以HTTPS开头的URL,而不是HTTP。这就是为什么您会发现当您尝试在现代浏览器中键入http://www.bing.com时,它会转换为https://www.bing.com。检查服务人员接下来,浏览器需要确定服务人员是否可以处理请求——这对于没有网络连接的离线用户来说至关重要。服务工作者是一个相对较新的浏览器功能。它通过拦截网络请求提供离线应用程序能力,这些请求可以保存在脚本控制的缓存中。这很有用,因为它可以让网站更好地控制何时使用缓存项。这些缓存是域绑定的,这意味着每个域都可以有自己的缓存黑盒,与其他域的缓存隔离。当访问一个页面时,可以注册一个Serviceworker。这个动作是由一个worker线程完成的,它可以在本地数据库中记录serviceworker的注册和URL映射。判断是否安装了serviceworker,只需要查看这个本地数据中是否有对应的url即可。如果为serviceworker找到了相应的URL,则允许它处理对请求的响应。而如果浏览器支持NavigationPreload这个新特性,并且开发者使用了,那么浏览器会同时发起第一个导航请求。这是有益的,因为它避免了由于serviceworker启动太慢而导致浏览器对页面渲染的影响。当浏览器发现没有serviceworker处理初始请求时,会继续到网络请求层。检查网络缓存浏览器通过网络请求层检查缓存中是否有新的响应。这通常由响应标头中的Cache-Control字段确定。字段中设置的max-age值可以决定多久缓存会被刷新,no-store字段可以表示是否应该缓存。可以想象,如果浏览器在缓存中找不到任何东西,那么它就需要进行网络请求。而如果缓存中有全新的响应,则会立即返回以供页面加载。如果有资源不够“新”,浏览器会将这个请求转化为条件验证请求,即在请求头中附加if-Modified-Since或If-None-Match告诉服务器当前浏览存储的是哪个版本的缓存。服务器可以返回一个HTTP304状态代码(无变化)来告诉浏览器缓存是最新的,而无需响应文本;或者返回一个HTTP200状态码,告诉浏览器缓存的资源已经过期,直接返回最新的资源检查网络连接如果有与主机和端口建立连接的请求,反而会被浏览器重用重新建立一个新的。否则浏览器会去网络层了解是否需要进行DNS(DomainNameSystem)查询。这个动作的具体过程是先查找本地的DNS缓存(存储在你的设备上),然后根据是否访问远程域名服务器(它们是由互联网服务提供商ISP分配的主机地址)来决定是否访问DNS缓存已过期,域名服务器最终会将准确的IP地址返回给浏览器进行连接。在某些情况下,浏览器可以提前知道将要访问哪些域名,从而先准备好与这些域名的连接。网页可以在链接标签中使用资源提示(resourcehints),如rel="preconnect",提示浏览器提前做好连接准备。资源提示在用户在Bing搜索结果页面等场景中很有用,通常预期前几个搜索结果最有可能被用户访问。这时候,提前准备好那些域名的连接,就可以节省那些网页被点击后的DNS查询和域名连接的消耗。连接建立浏览器现在可以与服务器建立连接,服务器知道它需要从客户端接收和发送消息。如果我们使用TLS,我们需要执行TLS握手过程来验证服务器提供的证书。向服务器发送请求通过此连接发起的第一个请求称为顶级页面请求。通常,请求的资源是一个HTLML文件,由服务器返回给客户端处理响应。当响应以数据流的形式到达客户端时,客户端开始解析它。首先,浏览器检查响应标头。作为HTTP响应的一部分,HTTP标头采用键值对的形式。如果响应头指示重定向(例如,通过Location字段),浏览器将再次导航并返回原始步骤以检查是否需要执行HSTS升级(到HTTPS)。如果服务器的响应数据被压缩或分块,浏览器将尝试解压缩并合并它。响应被解释后,浏览器将其并行写入网络缓存。浏览器然后计算出正在发送的文件的MIME类型,以便它可以适当地加载文件。例如,图像文件将被完整加载,但HTML文件将被解析和呈现。如果调用HTML解析器,它会扫描出可能下载的资源文件的URL,以便浏览器可以在页面呈现之前开始下载。这部分的更多细节将在本系列的下一篇文章中展开。截至目前,所请求的导航URL已被输入到浏览器的历史记录中,以便它可以用于浏览器导航的前进和后退功能。这里有一个更详细的流程图,可以让你大致了解正在讨论的内容:如你所知,页面将继续发出请求,因为页面上仍然有许多对整体体验很重要的子资源,例如图像、脚本和样式表。此外,这些子资源中引用的其他资源,如背景图片(在CSS中引用),或者其他由fetch()、import()、AJAX请求发起的资源。没有这些,我们只会看到一个没有交互的原始空白页面。再说说缓存刚才说了,浏览器会管理网络缓存,让下载的资源可以在各种场景下复用。这对于长时间不更新的资源特别有用,例如徽标和第三方脚本文件。我们应该尽可能地利用好这些缓存,因为这将有助于减少外部网络请求的数量,并将其替换为本地可重用的缓存资源。响应头中的Cache-Control字段控制浏览器的缓存逻辑。在某些情况下,您可以安全地告诉浏览器根本不要缓存,例如使用Cache-Control:no-store,因为资源预计会一直发生变化。另一种情况,当给定URL的响应内容永远不会改变时,我们可以设置Cache-Control:immutable以便浏览器可以永远缓存它。在实际应用中,当我们使用不同的URL指向同一个资源的不同版本时,我们可以使用这种方式来代替改变同一个URL的资源,因为缓存的版本会一直被使用,不会发送请求。Origin模型Origin由协议、主机名和端口组成。例如https://www.bing.com:443的origin由https协议、www.bing.com的主机名和443的端口组成,只要其中任何一部分不同,当将两者进行比较,它们将被视为不同的来源。例如,https://images.bing.com:443和http://www.bing.com:80来自不同的来源。Origin对于浏览器来说是一个重要的概念,因为它定义了数据是如何被隔离和保护的。在大多数情况下,出于安全原因,浏览器会强制执行同源策略,这意味着一个来源无法访问另一个来源的数据。就像上面提到的两个来源——https://images.bing.com:443和http://www.bing.com:80一样,它们都不能访问彼此的缓存(serviceworker的)。如果bing.com想要从microsoft.com加载Javascript文件,它需要在执行同源策略的浏览器中发出跨域资源请求。为此,microsoft.com需要通过指定CORS(跨源资源共享)标头与bing.com合作。总结现在您了解了资源如何从服务器到客户端以及两者之间的详细信息,请继续进行网页加载的下一步:从HTML标记到DOM。ps:欢迎关注微信公众号——前端漫游攻略,会定期发布优质原创文章和翻译。关注公众号福利:回复666获取高级前端电子书精选,谢谢~
