为什么要提高网络性能?Web性能的黄金法则:只有10%~20%的最终用户响应时间花在下载html文档上,其余80%~90%花在下载页面组件上。 web性能对用户体验有重要影响,根据著名的`2-5-8`原则:当用户在2秒内得到响应时,系统会感觉响应非常快;当用户在2-5秒内得到响应如果在5-8秒内得到响应,你会觉得系统的响应速度还可以。当用户在5-8秒内得到响应时,你会觉得系统的响应很慢,但是可以接受。当用户在8秒后没有得到响应时,你会觉得系统很糟糕,甚至系统已经挂了;要么打开竞争对手的网站,要么重新发起二次请求 一切都需要研究,通过科学研究才能发现事物的发展规律。在此感谢雅虎工程师总结的14条前端优化法则,让我们站在巨人的肩膀上。《高性能网站建设》本书中的14条优化原则总结如下:减少HTTP请求内部页面优化启用缓存减少下载优化网络连接为什么减少HTTP请求可以提高Web性能? 要回答这个问题,我们需要了解浏览器向服务器发送http请求时获取数据的过程: 打开一个链接(tcp/ip三次握手过程)-》发送请求-》等待(网络延迟和服务器处理时间)->下载数据 我们来看看百度首页http请求的每个阶段所花费的时间。上图不同的颜色代表下图中的不同阶段 可以看到除了图片,其他大部分的http请求事件都花在了连接建立和等待阶段。 http协议建立在TIC/IP协议之上。在TCP/IP协议中,TCP协议提供可靠的连接服务,使用三次握手建立连接。简单来说,三次握手就是一个身份确认的过程: (第一次握手:主机A发送一个syn=1的比特码,随机生成一个seqnumber=1234567的数据包给服务器,主机AB发送SYN=1是的,A请求建立连接;)晴儿:你是肖哥吗?seq+1),syn=1,ack=1,随机生成一个seq=7654321的数据包)小健:这家伙是谁啊? (第三次握手:主机A收到后检查ack号是否正确,即第一次发送的seq号+1,位码ack是否为1,如果正确则主机A发送ack号再次=(主机B的seq+1),ack=1,主机B收到后确认seq值,ack=1,则连接建立成功。)青儿:这首诗。..你真是萧兄,一萧一剑走江湖,一生一次的情与愁。..萧剑:晴儿,你真的是晴儿。...(啪、啪、啪、啪、啪、啪、啪....) 言归正传,这个过程也是需要时间的。我在百度首页找到了一个极端的例子: 而且等待的时间通常比下载内容的时间要长,这里也举一个极端的例子: 由此我们可以得出一个结论:大部分时间http请求花费在建立连接和等待时间上,优化方法是减少http请求。如何提高网络性能? 1。减少http请求 一般来说,减少http请求有两种方式:减少对图片的请求,减少对脚本文件和样式表的请求 通常减少图片的方式有两种:csssprites,inlineimages,IconFont. CSSSprites:将多张图片合并为一张图片,利用css的background-position属性,将html元素的背景图片放置在sprites图片中想要的位置。使用此技术的另一个优点是它减少了下载大小,合并后的图像比拆分图像小,因为它减少了图像本身的开销(颜色映射、格式信息等)。CSSsprites在实际项目中是一个体力活,因为在开发过程中需要对这张大图进行维护(增减图)。张新旭的文章介绍了如何管理精灵图像可以作为参考(这里)。如果您需要在页面中为背景提供大量图像,链接、导航栏、csssprites绝对是一个很好的解决方案(干净的标签、更少的图像、更短的响应时间)。 内联图像:图像可以包含在页面中,无需任何额外请求,使用数据:URL模式。缺点是IE8以下的浏览器不支持这种方式,而且IE8对数据大小有限制,只能支持23kb以内的数据。对于较小的图片,可以直接内联到网页中,但是对于大图片,内联到页面中会导致页面变大。聪明的做法是使用css,将内联图片作为背景,放在一个外部样式表中,这意味着数据可以缓存在样式表内部。尽管使用外部样式表会添加一个http请求,但浏览器可以缓存该样式以获得额外收益。还有一点需要注意:base64是有损压缩。 IconFont:图标字体,是近几年新流行的一种图片替换字体技术。它可以适应任何分辨率而不会出现图像模糊。与图片相比,容量更小,灵活性更高(和字体一样,可以设置图标大小、颜色、透明度、悬停状态、反转等),IE8以上浏览器支持该技术。在使用IconFont之前,首先要确定你选择的字体库是否免费。详细可以参考这篇文章:浅谈图标字体化 减少对脚本和样式表的请求主要原则是合并。在实际开发中,我们遵循模块化的原则,将代码分散到很多小文件中。按照软件开发的原理,这是完全正确的,但是对于在线页面来说,每个文件都会产生一次http请求,严重影响性能。与CSSsprites一样,将这些小文件组合成一个文件可以减少http请求的数量并缩短最终用户的响应时间。在合并过程中,我们还需要使用工具进行简化(删除不必要的字符以减少文件大小和下载时间)和混淆(除了删除不必要的字符外,我们还重写源代码,例如函数和变量名使用更短的标量名称)Javascript代码。对于使用AMD或者CMD进行模块化开发的同学,在合并的过程中,其他依赖的模块通常会被打包成一个文件,模板html通常会以字符串的形式内联到Javascript文件中。目前最常用的前端构建工具是glup。这里有一篇初步的应用文章:前端|gulppackagerequire.js模块依赖 2.页面内部优化 页面内部优化的主要方向:样式表放在顶部,脚本文件放在底部,避免css表达式,脚本样式表放在外部,以及去除重复脚本 关注性能的工程师希望页面能尽快展现在用户面前。我们都希望页面的内容能够逐渐加载,给用户提供视觉反馈。将样式表放在底部会导致浏览器阻止内容逐渐呈现。为避免页面变化时重绘页面元素,浏览器会阻塞页面渲染,直到样式表解析完毕(详见我的博客)。所以将样式表放在顶部并不会减少资源加载时间,它会减少页面呈现时间。小米主页曾经犯过这样一个错误: 把样式表放在底部会挡住页面的渐变渲染,把脚本文件放在页面的顶部也会挡住页面的渐变渲染。script元素会阻塞后续内容的解析,因为脚本可以通过document.write改变页面。解决办法是将脚本标签放在页面底部。这样不仅可以让内容渐进式渲染,还可以提高下载的并行度。如果我们确定不需要document.write,我们可以在script标签中添加asyn属性(IE中添加了defer)来提高并行下载速度。 CSS表达式是ie支持的一种方法,可以用来动态改变CSS属性。我们不需要知道太多。其写法如下。一旦在产品中发现表达式关键字,它将被彻底淘汰。 使用外部脚本和样式,我想任何有经验的工程师都会这样做。 去除重复脚本:这篇文章主要是为了避免多次在页面中添加相同的Javascript代码。如果我们开发中有AMD、CMD等依赖管理方式,基本不会出现这种情况。 3.启用缓存 关于缓存的使用这里有两套方案:expires/If-Modified-Since,Cache-Control/Etag;前者是HTTP1.0中的缓存方案,后者是HTTP1.1中的缓存方案,如果两者都出现在http头中,则后者的优先级更高。 If-modified-since方式通常称为条件Get。文件的副本存储在浏览器的缓存中,但需要询问服务器该副本是否可用。If-Modified-Since表示浏览器向服务器发送最新的修改时间,与服务器对应的header中的Last-Modified进行比较;如果If-Modified-Since<=Last-Modified,浏览器读取本地副本。此时响应状态为304NotModified,没有发送响应体。 Expries:虽然使用条件GET和304响应可以节省时间,但是浏览器和服务器仍然需要发送确认请求。可以通过显式设置副本的过期时间来避免有条件的GET。当浏览器在响应头中发现expires时,会将过期时间和文件保存在缓存中。从缓存中读取直到过期。expiresheader用一个特定的时间来指定缓存的有效期,他要求浏览器和服务器的时间完全一致。并且一旦过期,需要在服务端配置中重新设置一个过期时间。 ETag(EntityTag):是服务端用来检查浏览器缓存合法性的一种机制。ETag是在HTTP1.1中引入的,ETag是一个字符串,用来唯一标识一个组件的特定版本。唯一的格式约束是字符串必须用双引号引起来。如果浏览器要验证一个组件是否有效,它会使用If-None-Match将etag字符串发送到服务器。如果ETag匹配,服务器将返回304。(如果实体数据需要根据User-Agent或Accept-Language进行更改,ETag提供了更大的灵活性)。对于使用服务器集群的网站,ETag通常无法从一台服务器匹配到另一台服务器。这是ETag的问题。甚至同时使用If-Modified-Since和If-None-Match也达不到预期的效果。总是有一个解决方案:自定义Etag格式 Cache-Control:HTTP1.1引入而不是Expires,它使用max-age指令来指定副本被缓存多长时间,它定义了一个秒更新窗口,如果从请求组件到现在的秒数小于设置值,将一直使用副本。避免了http请求。与Expries相比,Cache-Control指令提供更细粒度的控制。详细可以参考Dae同学的文章:通过浏览器查看HTTP缓存 4.减少下载 减少下载最有效的方法就是启用gzip压缩,gzip压缩是GNU开发的一种免费格式。压缩组件通过减少http响应的大小来加速响应。HTTP1.1使用Accept-Encoding来识别支持的压缩。如果服务器看到此标识,它将使用请求标头中的方法来压缩响应。并通过Content-Encoding通知Web客户端。很多网站都会压缩html文件。其实包括xml、json在内的任何文本都可以压缩,但是图片、pdf就不要压缩了。根据经验,通常可以压缩大于1kb或2kb的文件。压缩通常会将响应中的数据量减少70%。压缩的代价是:服务端需要花费额外的cpu进行压缩,客户端需要解压。所以需要在cpu消耗和数据块大小之间做一个权衡。 5.优化网络连接 网络连接优化的三个主要规则:使用CDN加速、减少DNS查找、避免重定向 CDN:CDN是地理分布的Web服务器的集合,用于更高效地发布内容。通常根据网络的远近,选择服务于特定用户的网络服务器。这缩短了资源传输响应时间,有效提高了网络性能。 DNS用于映射主机名和IP地址。通常,一个分辨率需要20-120毫秒。浏览器会先根据页面的主机名进行域名解析,直到ISP返回结果后页面才会加载任何内容,因此减少DNS查找可以有效减少等待时间。为了获得更高的性能,DNS解析通常在多个层面进行缓存,例如ISP或LAN维护的缓存服务器、本机操作系统的缓存(如windows上的DNSClientService)、浏览器。IE默认的DNS缓存时间是30分钟,Firefox默认的缓存时间是1分钟。我们能做的是最小化一个页面的主机名,但是我们必须在浏览器的最大并行下载数和dns查找之间做一个权衡。根据雅虎的研究,***将主机名控制在2-4之间。 重定向:将一个URL重新路由到另一个URL。重定向功能是通过301和302这两个HTTP状态码来完成的,比如:HTTP/1.1301MovedPermanentlyLocation:http://example.com/newuriContent-Type:text/html浏览器自动将请求重定向到指定的LocationURL重定向的主要问题是它们会降低用户体验。资源最密集、最频繁且最容易被忽视的重定向之一是URL中缺少/。自动生成尾部斜杠的原因是浏览器在发出get请求时必须指定一些路径;如果没有路径,它将简单地使用文档根目录。(如果主机缺少尾部斜杠,则不会发生重定向:http://www.baidu.com)没有尾部斜杠的重定向是许多Web服务器的默认行为。需要在服务器端设置才能消除。下图是豆瓣的url请求: 雅虎的14条优化规则长期以来发挥了重要作用。随着技术的发展,单靠这14条原则已经不能满足前端性能优化了。前端工程的概念已经出现在一些大公司。详见本文:前端性能优化工程进阶 参考资料:web前端性能意义、重点、测试计划、WEB站点性能优化实践(加载速度提升2s)HTTP协议三-方式握手过程高性能WEB开发-为什么要减少请求数,如何减少请求数!我如何构造网站的CSS,图标字体化,说说使用ETag缓存通过浏览优化请求服务器看HTTP缓存
