原文请查阅这里,略有改动,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland。javascript
本系列持续更新中,Github 地址请查阅这里。java
这是 JavaScript 工做原理的第十二章。git
正如在以前关于渲染引擎的文章中所讲的那样,咱们相信好的和伟大的 JavaScript 开发者之间的差异在于后者不只仅只是理解了语言的具体细节还了解其内部构造和运行环境。github
49 年前,ARPAnet 诞生了。它是早期的报文分组交换网络及第一个实现 TCP/IP 协议套件的网络。该网络连通了加利福亚大堂和斯坦福研究所。20 年后,Tim Berners-Lee 分发了一个后来为人所熟知的万维网的 『Mesh』草案。在 49 年的时间里,网络走过了一段漫长的旅程,从仅仅只是是两台电脑间交换数据报文到至少 7500 万台服务器,38 亿人使用互联网以及 13 亿个网站。chrome
本文将试着分析现代浏览器使用哪些技术来自动提高应用性能(有些你甚至不了解),而后着重介绍浏览器网络层。最后,提供一些让浏览器提高网络应用程序性能的技巧。跨域
现代浏览器专门为快速,高效和安全数据传输的网络应用/网站而设计开发的。拥有数以百计的组件运行于各个不一样的层级,从进程管理和安全沙箱到 GPU 管线,音频和视频及其它更多等等,网络浏览器更相似于一个操做系统而不只仅只是一个软件。浏览器
浏览器的总体性能是由一些大型的组件所决定的,这些组件包括:解析,布局,样式计算,JavaScript 和 WebAssembly 执行,渲染,固然还有网络堆栈。缓存
通常状况下,工程师们会把网络堆栈当作是一个性能瓶颈。常常会发生这样的状况由于从网络抓取全部的资源会堵塞渲染剩下的步骤。为了更加高效的网络层,它须要不只仅只是扮演套接字管理员的角色。在咱们看来获取资源是一个很是简单的机制,可是实际上它集成自身的优化准则,接口和服务的一整套平台。安全
网页开发者不须要担忧单独的 TCP 或者 UDP 数据包,请求格式化,缓存以及其它正在发生的一切。浏览器会处理这些复杂的玩意,这样就能够专一开发本身的程序。可是,知道其内部的原理能够帮助开发者开发出更加高效和安全的程序。服务器
本质上,当用户开始和浏览器发生交互所产生的状况以下:
W3C Navigation Timing specification 提供了浏览器接口及浏览器中每一个请求背后的可视化计时和性能数据。让咱们浏览下这些组件,由于每一个组件在获取最佳用户体验方面扮演了重要的角色。
整个网络请求过程是至关复杂的而且有许多的层次结构,每一层都有可能成为性能瓶颈。这就是为何浏览器使用各类技术努力提高其性能,以便把整个网络通讯的性能损耗降至最低。
看些新技术吧:
JavaScript 和 WebAssembly 禁止开发者操做单独的网络套接字的生命周期,这样是至关的明智的。这样不只仅可让你头发少掉点并且可让浏览器自动优化大量的性能,这些性能包括套接字重用,请求优化和延迟绑定,协议协商,强制链接限制及其它的优化措施。
实际上,现代浏览器更一步地将请求管理周期从套接字管理中剥离了出来。用套接字池来组织套接字,以源来分组套接字,每一个套接字池强制限制其链接数和安全约束。排队,优先化等待的请求,而后和套接字池中的单个套接字绑定。若是不是服务器主动关闭这些链接,多个请求能够自动重用相同的套接字。
因为建立一个新的 TCP 链接会带来额外的性能开销,重用链接会为其自带来极大的性能提高。默认状况下,当发起请求的时候,浏览器使用所谓的 『keepalive』机制以节省建立到服务器的新链接所耗费的时间。建立一个新的 TCP 链接的平均时间为:
这样的架构衍生出了一些其它的优化方法。请求能够依据优先级来以不一样的顺序执行。浏览器能够优化全部套接字间的带宽分配或者它能够建立套接字以等待预期的请求。
如上所述,这些都是浏览器所控制而不用开发者进行干预。但这并不意味着咱们无所事事了。选择正确的数据传输所用的网络通讯模式,类型和频率,正确的协议类型以及正确的服务器堆栈隧道/优化对于提高整个程序的性能有着相当重要的做用。
一些浏览器甚至更进一步。例如,当你使用 Chrome 的时候,当用户使用的时候它会进行自我学习从而变得更加快速。它基于访问过的网页和典型的浏览器模式来进行学习,这样就能够预期可能的用户行为且在用户进行任意操做以前进行操做。最简单的例子即当用户悬停在某个连接上的时候预渲染页面。若是你想学习更多关于 Chrome 优化技术的文章,能够查看 High-Performance Browser Networking 这本书的 www.igvita.com/posa/high-p… 章节。
容许浏览器操做单独的套接字有另外一个很是重要的目的即:浏览器就能够针对不被信任的程序资源强制实施一套一致的安全和政策约束措施。例如,浏览器禁止经过 API 直接访问原始网络套接字,由于这样会致使任意可疑的程序随意链接任意主机。浏览器也强制链接数限制以保护服务器免受因为客户端访问而耗尽其资源。
浏览器格式化全部流出的请求以强制格式正确和一致的协议语义来保护服务器。一样地,浏览器会自动解码响应内容以保护用户免受可疑服务器的攻击。
Transport Layer Security (TLS) 是一个为计算机网络提供通讯安全的加密协议。它普遍应用于大量应用程序,其中之一即浏览网页。网站可使用 TLS 来保证服务器和网页浏览器之间的全部通讯安全。
整个 TLS 握手过程包含如下几个步骤:
每当发生任何验证失败的时候,用户会收到警告。好比服务器使用自签名的证书。
当两个页面的协议,端口(若是有指定)以及主机名都是同样的则称为同源。
如下为一些可能包含跨域的资源示例:
<script src=”…”></script>
里面的 JavaScript 代码。语法错误的错误信息仅适用于同源脚本。<link rel=”stylesheet” href=”…”>
的 CSS。因为 CSS 的松散语法规则,跨域 CSS 要求正确的 Content-Type 头。各个浏览器的限制不一样。<img>
图片<video>
和 <audio>
媒体文件<object>
, <embed>
和 <applet>
插件以上的列表还远远不够;该列表旨在强调工做中的『最小特权』原则。浏览器只为应用程序代码暴露出其所必需的接口和资源:应用提供数据和 URL 地址,而后浏览器格式化请求及处理每条链接的整个生命周期。
须要注意的是并无一个简单的 『同源策略』概念。
相反,有一系列相关的机制来强制限制浏览器的 DOM 访问,cookie 和 会话状态管理,网络链接和其它组件。
最好和最快的请求即不建立请求。在分派一个请求前,浏览器自动检查其资源缓存,进行必要的验证检查而后当指匹配指定的条件时返回一份本地资源拷贝。若是缓存中没有可用的本地资源,则发起网络请求而后把响应内容自动放置于缓存中以备以后的访问(若是这是被容许的)。
管理一个高效和优化的资源缓存是很是困难的。谢天谢地,浏览器为咱们处理了整个复杂的玩意,而咱们所须要作的即保证服务器返回恰当的缓存指令;想了解更多能够看 客户端资源缓存 文章。你为网页上的全部资源添加 Cache-Control,ETag,和 Last-Modified 的响应头信息。
最后,一个常常被忽略但相当重要的浏览器功能即其提供了验证,会话和 cookie 管理。浏览器为每一个源维护单独的『cookie jars』,经过提供必要的程序和服务器接口来读写新的 cookie,会话和认证数据,以及自动挂载和处理适当的 HTTP 头来为咱们自动处理整个过程。
一个简单但明了的用来展现浏览器的延迟会话状态管理的方便性的例子即:多个选项卡或者浏览器窗口能够共享一个认证会话,反之亦然;一个选项卡中的登出操做可使全部其它打开窗口的会话失效。
了解了网络服务以后,最终要讲到应用程序接口和协议。众所周知,更底层的结构提供了一组普遍的重要服务:套接字和链接管理,请求和响应处理,各类安全策略,缓存及其它更多的强制措施。每当初始化一个 HTTP 请求或者 XMLHttpRequest,一个持久的服务推事件或者 WebSocket 会话抑或打开一个 WebRTC 链接,咱们就是在和部分或者全部这些底层服务进行交互。
没有单一的最佳协议或者接口。每一个复杂的程序都会基于不一样的要求混合使用不一样的传输协议:和浏览器缓存的交互,协议开销,消息延迟,可靠性,数据传输类型以及其它。一些协议拥有低数据传输延迟的特性(好比服务器推事件,WebSocket),可是可能不符合其它重要的场合,好比利用浏览器缓存或者支持任意状况下的二进制数据传输的能力。
今日头条招人啦!发送简历到 likun.liyuk@bytedance.com ,便可走快速内推通道,长期有效!国际化PGC部门的JD以下:c.xiumi.us/board/v5/2H…,也可内推其余部门!
本系列持续更新中,Github 地址请查阅这里。