从输入URL到页面可交互的过程探究之一:从服务端到客户端

2019-08-15 admin

原文:https://alistapart.com/articl…

最近发现国外有一个系列,专门探究从输入URL到页面可交互的详细过程,是一份干货十足的好资料。笔者决定分为四篇文章对其进行有删减地翻译,只希望能对大家有所帮助,毕竟这是前端必备的知识点,也是容易忽略掉某些细节的知识点。事先声明,这个系列完全由笔者手翻,如有翻译不当的地方,恳请读者给出改进意见!

接下来开始第一篇——从服务端到客户端

在浏览器执行任何工作之前,它需要先知道访问的是哪里。有几种方法可以实现访问:在地址栏中输入URL、点击(或触碰)一个页面上或其他app中的超链接、或者点击你的收藏。无论是哪种情况,都会触发一个动作——导航。导航永远是网页中交互的第一步,因为它触发了如下一系列事件的连锁反应直至网页被加载。

初始化请求

一旦URL被提供给浏览器去加载,以下这些事情就会悄悄在背后发生:

检查HSTS

首先,浏览器需要判断这个URL是否明确为HTTP(不安全)协议。如果它是一个HTTP的请求,那么浏览器则需要检查这个域名是否在HSTS的清单中(HTTP Strict Transport Security——严格安全传输)。这个清单包含了一个预加载好的名单以及你之前访问过的使用HSTS的网站名单,它们都是存放在浏览器中的。如果你请求的HTTP开头的host处于在HSTS清单中,那这个请求会被强制转为HTTPS开头的URL而非HTTP。这就是为什么你会发现当你试图在一个现代浏览器中输入http://www.bing.com 会被转为https://www.bing.com

检查SERVICE WORKERS

接着,浏览器需要判断service worker是否可以用来处理请求——这对于那些离线的没有网络连接的用户来说至关重要。Service workers相对来讲是比较新的浏览器特性。它通过对网络请求的拦截来提供离线应用的能力,这些请求都可以被保留在脚本控制的缓存中。这是很有用的,因为它使网站能够更好地控制何时使用缓存的项目。这些缓存是跟域名绑定的,这意味着每个域都可以有自己的缓存黑盒,并与其他域的缓存隔离开。

当一个页面被访问时,可以注册一个Service worker,这个动作是由一个工作线程来完成的,它可以把service worker的注册和URL映射记录在本地数据库中。要判断一个service worker是否被安装,只需在这个本地数据中查找是否有对应的URL。如果为service worker查到了对应的URL,它就会被允许处理请求的回应。而如果浏览器支持Navigation Preload的新特性,且开发者使用了它,那么浏览器会同时去发起首次导航请求。这是有好处的,因为它避免了浏览器因为service worker启动过慢而对页面渲染的影响。

当浏览器发现没有service worker来处理初始化请求时,就会继续网络请求层。

检查网络缓存

浏览器会通过网络请求层检查缓存中是否存在全新的响应。这经常是由响应头中的Cache-Control字段决定的,字段中设置的max-age值可以决定缓存多久会刷新,而no-store字段可以表明是否应该被缓存。可想而知,如果浏览器在缓存中找不到任何东西,那么就需要进行网络请求了。而如果在缓存中有一个全新的响应,它就会被立即返回以用于页面加载。如果存在一个不够“新”的资源,那么浏览器会把这个请求转为一个附带条件的校验请求,也就是请求头带上If-Modified-Since或者If-None-Match去告诉服务端当前浏览器存的是哪个版本的缓存。服务端则可以返回HTTP 304状态码(没有更改)告诉浏览器这个缓存是最新的,不带响应正文;或者返回HTTP 200状态码告诉浏览器这个缓存资源已经过期了,并直接返回最新的资源

检查网络连接

如果现在有一个和主机、端口建立起连接的请求,那么它会被浏览器复用而不是重新去建立一个,否则,浏览器会走网络层以了解是否需要执行DNS(域名系统)查询。这个动作的具体流程是,先寻找本地的DNS缓存(存储在你的设备上),然后根据DNS缓存是否过期来决定是否访问远程域名服务器(它们由互联网服务提供商ISP分配主机地址),域名服务器最终会返回准确的IP地址给浏览器进行连接。

某些情况下,浏览器能够预先知道哪些域名会被访问,从而先准备好对这些域名的连接。一个网页可以通过在link标签中使用资源提示(resource hints),比如rel=“preconnect” 来提示浏览器提前准备好连接。在如下场景中,资源提示是很有用的,比如一个用户在必应的搜索结果页,而通常的预期中,前几条搜索结果是最有可能被用户访问的。此时,提前准备好对那些域名的连接可以在那些网页被点击之后节省掉DNS查询和域名连接的消耗。

建立起连接

浏览器现在可以与服务器建立起连接了,且服务端知道自己需要从客户端接收和发送消息了。如果我们是使用TLS,我们需要执行一次TLS握手流程以验证服务器提供的证书。

发送请求给服务器

第一个通过这个连接发起的请求叫做顶级页面请求。通常情况,这个请求的资源会是一个HTLML文件,从服务器返回到客户端

处理响应

当响应以数据流的形式到达客户端后,客户端就开始进行解析了。首先,浏览器会检查响应头。HTTP头部是以键值对的形式作为HTTP响应的一部分。如果响应头指示要进行重定向(比如,通过Location字段),浏览器就会再一次进行导航并回到最初的那一步,检查是否需要执行HSTS的升级(为HTTPS)。

如果服务器的响应数据被压缩或分块了,浏览器会尝试对它进行解压和合并。

待响应被解读完成后,浏览器还会并行地将其写入网络缓存中。

接着,浏览器会搞清发送过来的文件的MIME类型,这样它才能以适当的方式去加载这份文件。比如,一份图片文件会原封不动地被加载进来,但HTML文件则会被执行解析和渲染。如果HTML解析器被调用了,那么它会扫描出那些可能要下载的资源文件的URL,以便浏览器在页面渲染之前就可以开始去下载。这一部分的更多细节会在系列文章的下一篇中具体展开。

截至目前,被请求的导航URL已经输入到了浏览器的历史中,这样它就可以被用于浏览器导航的前进和后退功能了。

这里有一张更详细的流程图,它可以让你对目前讨论的内容有个总体的概览:

如你所知的,页面会继续发起请求,因为页面上还有很多对整体体验很重要的子资源,比如图片,脚本,和样式表。另外,这些子资源中引用到的其他资源,比如背景图片(CSS中引用的),或者其他由fetch()import()AJAX请求发起的资源。如果没有这些的话,我们将只能看到一个原始的无交互的空页面。

再谈缓存

刚刚已经提到,浏览器会管理网络缓存,以便在多种场景下能对下载好的资源的重复利用。这对那些长久不更新的资源尤其有用,比如logo和第三方的脚本文件。我们应该尽可能地利用好这些缓存,因为这有利于减少对外的网络请求数,取而代之的是本地的可复用的缓存资源。

响应头中的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 ,它们互相都无法访问对方的缓存(service worker的)。

如果bing.com想要从microsoft.com加载一个Javascript文件,它就需要在实行同源策略的浏览中发起一个跨域资源请求。想要允许这种操作的话,microsoft.com就需要与bing.com通过指定CORS(跨域资源共享)的头部进行合作。

总结

既然你已经明白了资源如何从服务器走到客户端以及之间的所有细节,那么请继续关注网页加载的下一步:从HTML标签转为DOM。

ps:欢迎关注微信公众号——前端漫游指南,刚刚开设不久,会定期发布优质原创文章和译文,感谢~ 图片描述

[转载]原文链接:https://segmentfault.com/a/1190000020076547

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-72518.html

文章标题:从输入URL到页面可交互的过程探究之一:从服务端到客户端

相关文章
vue 数组遍历方法forEach和map的原理解析和实际应用
一、前言 forEach和map是数组的两个方法,作用都是遍历数组。在vue项目的处理数据中经常会用到,这里介绍一下两者的区别和具体用法示例。 二、代码 1. 相同点 都是数组的方法 都用来遍历数组 两个函数都有4个参数:匿名函数中可传3...
2018-11-15
js性能优化 如何更快速加载你的JavaScript页面
确保代码尽量简洁 不要什么都依赖JavaScript。不要编写重复性的脚本。要把JavaScript当作糖果工具,只是起到美化作用。别给你的网站添加大量的JavaScript代码。只有必要的时候用一下。只有确实能改善用户体验的时候用一下。 ...
2015-11-12
10个强大的纯CSS3动画案例分享
我们的网页外观主要由CSS控制,编写CSS代码可以任意改变我们的网页布局以及网页内容的样式。CSS3的出现,更是可以让网页增添了不少动画元素,让我们的网页变得更加生动有趣,并且更易于交互。本文分享了10个非常炫酷的CSS3动画案例,希望大家...
2015-11-16
请前往任务中心完善资料即可激活会员
登录后,点击右上角的用户名,在下拉菜单中可以进去“我的任务” 注册自动激活,本站没有VIP!没有充值!没有推广任务等等 回复即可下载 ...
2015-11-18
v-charts | 饿了么团队开源的基于 Vue 和 ECharts 的图表工具
在使用echarts生成图表时,经常需要做繁琐的数据类型转化、修改复杂的配置项,v-charts的出现正是为了解决这个 痛点。基于Vue2.0和echarts封装的v-charts图表组件,只需要统一提供一种对前后端都友好的数据格式 设置简...
2018-05-24
从2014年的发展来展望JS的未来将会如何
<font face="寰�杞�闆呴粦, Arial, sans-serif ">2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
12个你未必知道的CSS小知识
虽然CSS并不是一种很复杂的技术,但就算你是一个使用CSS多年的高手,仍然会有很多CSS用法/属性/属性值你从来没使用过,甚至从来没听说过。 1.CSS的color属性并非只能用于文本显示 对于CSS的color属性,相信所有Web开发人员...
2015-11-12
破解前端面试(80% 应聘者不及格系列):从 闭包说起
不起眼的开始 招聘前端工程师,尤其是中高级前端工程师,扎实的 JS 基础绝对是必要条件,基础不扎实的工程师在面对前端开发中的各种问题时大概率会束手无策。在考察候选人 JS 基础的时候,我经常会提供下面这段代码,然后让候选人分析它实际运行的结...
2017-06-02
ajax为什么令人惊异?ajax的优缺点
使用Ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变的信息。 Ajax不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。就像DHT...
2015-11-12
HTML5的5个不错的开发工具推荐
HTML5规范终于在今年正式定稿,对于从事多年HTML5开发的人员来说绝对是一个重大新闻。数字天堂董事长,DCloud CEO王安也发表了文章,从开发者和用户两个角度分析了HTML对两个人群的优势。其实,关于HTML5的开发工具,我们以往的...
2015-11-12
回到顶部