这是探索 JavaScript 及其内建组件系列文章的第 12 篇。在认识和描述这些核心元素的过程当中,咱们也会分享咱们在构建 SessionStack 时所遵循的一些经验规则。SessionStack 是一个轻量级 JavaScript 应用,它协助用户实时查看和复现他们的 Web 应用缺陷,所以其自身不只须要足够健壮还要有不俗的性能表现。javascript
若是你错过了前面的文章,你能够在下面找到它们:前端
正如咱们在前一篇关于渲染引擎的文章中所说的,咱们相信,优秀的 JavaScript 开发者和杰出的 JavaScript 开发者之间的区别在于后者不只懂得如何使用这门语言,还可以理解它的内在以及周遭环境。java
49 年前,一个叫作 ARPAnet 的东西被创造了出来。它是一个早期的数据包交换网络,也是第一个实践 TCP/IP 套件的网络。该网络在加州大学和斯坦福研究中心之间搭建了一个链接。20年后,Tim Berners-Lee 发布了一个名为『Mesh』的提案,也就是后来人们所说的万维网。在这 49 年里,互联网走过了漫长的道路,从两台计算机交换数据包开始,到现在拥有超过 7500 万台服务器,38 亿名用户和 13 亿个网站。android
在这边文章中,咱们将尝试分析现代浏览器使用了哪些技术来自动地提升性能(有些你甚至并不知道)。咱们将尤为关注浏览器的网络层。在最后,咱们将会提供一些建议,关于如何使得浏览器可以更好地提高你的 Web 应用的性能。ios
为了可以快速、高效而且安全地展现 Web 应用/网站,现代的浏览器都是通过特别设计的。数百个组件运行在不一样的层上,从进程管理和安全沙盒到 GPU 流水线,音频和视频等等,Web浏览器看起来更像是一个操做系统,而不只仅是一个软件应用程序。git
浏览器的总体性能取决于许多大型组件:解析、布局、样式计算、JavaScript 和 WebAssembly 执行、渲染,固然还有网络栈。github
工程师常常认为网络栈是一个瓶颈。一般来讲,确实如此,由于在执行接下来的步骤以前,先得从互联网上获取到全部的资源。为了提升网络层的效率,它不只须要扮演简单的套接字管理员的角色。它呈现给咱们的只是一种很是简单的资源获取机制,但它其实是一个拥有本身的优化标准,API 和服务的完整平台。web
做为 Web 开发人员,咱们没必要操心个别的 TCP 或 UDP 数据包、请求格式化、缓存和此过程当中的其余全部事情。因此复杂的事务都由浏览器处理,所以咱们能够专一于咱们正在开发的应用程序。可是,了解底层究竟发生了什么,能够帮助咱们建立更快、更安全的应用程序。chrome
实质上,当用户开始与浏览器交互时发生了如下事务:编程
W3C 的导航时序规范提供了浏览器 API,它可以提供浏览器中每一个请求的生命周期背后的时间和性能数据。让咱们来看看这些组件,由于它们在提供最佳用户体验方面起着相当重要的做用:
这个网络通讯的过程是很是复杂的,有不少不一样的层可能成为瓶颈。这就是为何浏览器努力经过使用各类技术来提升性能的缘由,以便整个网络通讯的影响最小。
让咱们先从一些术语开始:
JavaScript 和 WebAssembly 不容许咱们管理网络套接字的生命周期,这是一件好事!这不只可使咱们免去不少麻烦,并且还可让浏览器自动去进行大量的性能优化,其中一些包括套接字重用,请求优先级和后期绑定,协议协商,强制链接限制等等。
实际上,现代浏览器更进了一步,把请求管理周期与套接字管理分立了开来。套接字按池组织,按源分组,每一个池强制实施本身的链接限制和安全约束。待处理的请求会先排队,再按优先级处理,而后绑定到池中的单个套接字上。除非服务器有意关闭链接,不然能够在多个请求中自动重用相同的套接字!
因为开辟新的 TCP 链接须要额外的成本,所以链接的重用具备很大的性能优点。默认状况下,浏览器使用所谓的「keepalive」机制,这能够节省出在已有请求发生后再打开新链接到服务器的时间。打开一个新的 TCP 链接的平均时间是:
23ms
120ms
225ms
这种架构为其余一些优化提供了可能。这些请求能够根据其优先级以不一样的顺序执行。浏览器能够优化全部套接字的带宽分配,或者在预期请求时先打开套接字。
正如我以前提到的,这一切都是由浏览器自行管理的,并不须要咱们作任何工做。但这并不必定意味着咱们什么都作不了。选择合适的网络通讯模式,传输类型和频率,恰当地选择协议以及调整/优化服务器架构能够在提升应用程序的总体性能方面发挥重要做用。
有些浏览器甚至更进一步。例如,Chrome 能够学习用户的操做习惯来使本身变得更快。它根据用户访问的网站和典型的浏览模式进行学习,以便在用户作任何事情以前预测可能的用户行为并采起行动。最简单的例子是当用户在连接上悬停时,Chrome 会预先渲染页面。若是您有兴趣了解有关 Chrome 优化的更多信息,能够查看高性能浏览器网络(High-Performance Browser Networking)一书中的本章节 www.igvita.com/posa/high-p…。
容许浏览器管理单个套接字具备另外一个很是重要的目的:经过这种方式,浏览器能够对不可信的应用程序资源强制执行一致的安全和策略约束。例如,浏览器不容许经过 API 直接访问原始网络套接字,由于这可使任何恶意应用程序与任何主机进行任意链接。浏览器还强制性地限制链接数,以保护服务器以及客户端免受资源耗尽的问题。
浏览器格式化全部传出请求,以强制实行风格一致且格式良好的协议语义来保护服务器。一样,响应解码自动完成,以保护用户免受恶意服务器的侵害。
传输层安全协定(TLS)是一种在计算机网络上提供安全通讯保障的加密协议。它在许多应用程序中普遍使用,其中之一是网页浏览。网站可使用 TLS 来保护其服务器和 Web 浏览器之间的全部通讯。
完整的 TLS 握手包含如下几步:
任何一步校验失败,用户都将会收到警告。例如,服务器正在使用自签名证书。
若是两个页面的协议、端口和主机名都相同的话,那么这两个页面同源。
如下是一些可能嵌入跨源资源的一些例子:
<script src=”…”></script>
引用 JavaScript 资源。语法错误的错误消息仅适用于同源脚本<link rel=”stylesheet” href=”…”>
引用 CSS 资源。因为 CSS 的宽松语法规则,跨源 CSS 须要正确的 Content-Type 标头。不一样浏览器可能有不一样的限制。<img>
引用图像资源。<video>
和 <audio>
引用多媒体资源。<object>
、<embed>
和 <applet>
引用插件资源。<frame>
和 <iframe>
引用的资源。网站可使用 X-Frame-Options 头部标识来阻止这种形式的跨源交互。以上列表远非完整;其目地是为了突出『最小特权』原则。 浏览器只公开应用程序代码必须的 API 和资源:应用程序提供数据和 URL,浏览器格式化请求并处理每一个链接的完整生命周期。
值得注意的是,『同源策略』并不是是个单一的概念。相反,有一组相关机制来强制性地限制 DOM 访问,Cookie 和会话状态管理,网络以及浏览器的其余组件。
最好和最快的请求是未发出的请求。在分派请求以前,浏览器会自动检查其资源缓存,执行必要的验证检查,并在知足指定条件时返回资源的本地副本。若是本地资源在缓存中不可用,则会发出网络请求,而且响应会被自动放入缓存中以供后续访问(若是容许)。
管理高效和优化的资源缓存是很困难的。值得庆幸的是,浏览器替咱们完成了全部复杂的事务,咱们只须要确保咱们的服务器返回适当的缓存指令;要了解更多信息,请参见客户端上的缓存资源(Cache Resources on the Client)。您确实有为网页上的全部资源都提供了 Cache-Control,ETag 和 Last-Modified 响应头部字段,对吧?
最后,浏览器常常被忽视但相当重要的功能是提供身份验证,会话和 cookie 管理。浏览器为每一个源维护单独的「Cookie jars」,提供必要的应用程序和服务器 API 来读取和写入新的 Cookie,会话和身份验证数据,并自动附加上和处理相应的 HTTP 头以代替咱们自动执行整个过程。
用一个简单但有说明性的例子来讲明将会话状态管理推放到浏览器端的便利之处:同一个通过身份验证的会话能够在多个选项卡或浏览器窗口之间共享,反之亦然;单个选项卡中的注销操做将使全部其余打开的窗口中打开的会话失效。
研究完了网络服务,终于到达了应用程序 API 和协议这一步。正如咱们所看到的,较低层提供了一系列关键服务:套接字和链接管理、请求和响应处理、各类安全策略的执行、缓存等等。每次咱们启动一个 HTTP、一个XMLHttpRequest 或是一个长期的 Server-Sent Event 或 WebSocket 会话,或是打开一个 WebRTC 链接,咱们都在与这些底层服务的一部分或所有进行交互。
没有单一的最佳协议或 API。每一个不平凡的应用程序都须要根据各类需求混合使用不一样的传输:与浏览器缓存的交互、协议开销、消息延迟、可靠性、数据传输类型等等。某些协议可能提供低延迟传输(例如 Server-Sent Events,WebSocket),但可能不符合其余关键条件,例如在全部状况下都可以利用浏览器缓存或支持高效二进制传输。
性能和安全性二者都是 SessionStack 中的一等公民。咱们没法妥协的缘由在于,一旦 SessionStack 集成到您的 Web 应用程序中,它就会开始监视从 DOM 更改、用户交互到网络请求,未处理的异常和调试消息的全部内容。全部数据都会实时传输到咱们的服务器上,这样您就可以以视频的形式重现用户遇到的一切状况。 而这一切都是以最短的延迟进行的,不会对应用程序形成任何额外的性能开销。
这就是为什么咱们努力实践以上全部提示,以及咱们将在将来发布的内容中讨论的更多内容。
若是你想试一试 SessionStack,这有一个免费的计划。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。