Web性能优化:What? Why? How?

发布时间:2026/7/3 1:10:49
Web性能优化:What? Why? How? Web性能黄金准则只有10%~20%的最终用户响应时间花在了下载html文档上其余的80%~90%时间花在了下载页面组件上。web性能对于用户体验有及其重要的影响根据著名的2-5-8原则当用户在2秒以内得到响应会感觉系统的响应非常快当用户在2-5秒之内得到响应会感觉系统的响应速度还可以当用户在5-8秒之内得到响应会感觉系统的响应非常慢但还可以接受当用户在8秒之后都没有得到响应会感觉系统糟透了甚至系统已经挂掉要么打开竞争对手的网站要么重新发起第二次请求凡事都需要研究通过科学的研究我们就可以找到事物的发展规律。这里要感谢雅虎的工程师总结的14条前端优化法则使得我们可以站在巨人的肩膀上。《高性能网站建设》这本书中的14条优化原则总结起来主要是以下个方面的优化减少HTTP请求页面内部优化启用缓存减少下载量网络连接上的优化为什么减少HTTP请求可以提高Web性能要回答这个问题我们就要了解当浏览器向服务器发送一个http请求知道获取数据都经历哪些过程开启一个链接tcp/ip的三次握手过程 -》 发送请求 -》 等待网络延迟跟服务器的处理时间-》 下载数据我们看一下百度首页中的http请求在各阶段耗费的时间上面不同的颜色代表下图中的不同阶段可以看到除了图片之外其余大部分http请求的事件花在了建立连接与等待阶段。http协议建立在TIC/IP协议之上在TCP/IP协议中TCP协议提供可靠的连接服务采用三次握手建立一个连接。 简单来说三次握手就是一个身份确认的过程第一次握手主机A发送位码为syn1,随机产生seq number1234567的数据包到服务器主机B由SYN1知道A要求建立联机晴儿你是潇哥哥吗我是晴儿第二次握手主机B收到请求后要确认联机信息向A发送ack number(主机A的seq1),syn1,ack1,随机产生seq7654321的包潇剑这货是谁一箫一剑走江湖下一句是什么第三次握手主机A收到后检查ack number是否正确即第一次发送的seq number1,以及位码ack是否为1若正确主机A会再发送ack number(主机B的seq1),ack1主机B收到后确认seq值与ack1则连接建立成功。晴儿这首诗。。。你真的是潇哥哥一萧一剑走江湖千古情愁酒一回。。。潇剑晴儿你真的是晴儿。。。。啪啪啪啪啪啪啪啪啪啪啪啪啪啪啪。。。。。。。。。。。。言归正传这个过程也是需要消耗时间的在百度首页找到一个极端的例子而等待的时间通常也大于内容下载的时间这里同样找到一个极端例子由此我们可以得出结论一个http请求绝大多数的时间消耗在了建立连接跟等待的时间优化的方法是减少http请求。如何提高web性能1、减少HTTP请求一般来说要减少http请求通常从两个方面下手减少图片的请求、减少脚本文件与样式表的请求图片的减少通常有两种方式css sprites、内联图片、IconFont。CSS Sprites将多张图片合并成一幅单独的图片使用css的background-position属性将html元素的背景图片放到sprites 图片中的期望位置上。使用这项技术的附加优点是他降低了下载量合并后的图片比分离的图片和更小因为它降低了图片自身的开销颜色表、格式信息等等。实际项目中css sprites是一项体力活因为开发过程中需要对这张大图进行维护添加、减少图片张鑫旭同学的文章中有介绍如何管理sprites图片可以作为参考这里。如果需要在页面中为背景、链接、导航栏提供大量的图片css sprites绝对是一种优秀的解决方案干净的标签、较少的图片、较短的响应时间。内联图片通过使用data:URL模式可以再页面中包含图片而无需任何额外的请求。缺点就是IE8以下的浏览器不支持这种方式而IE8在数据大小上有限制只能支持23kb以内的数据。对于较小的图片来说可以直接内联到web页面中但对于大图片内联到页面里会导致页面变大聪明的做法是使用css将内联的图片作为背景使用并放到外部样式表中这意味着数据可以缓存在样式表内部。使用外部样式表虽然增加了一个http请求但样式可以被浏览器缓存得到额外的收获。另外一点需要注意base64是有损压缩。IconFont图标字体这是近年来新流行的一种以字体代替图片的技术。它可以适应任何分辨率而不会出现图片模糊问题与图片相比它具有更小的容量更高的灵活性像字体一样可以设置图标大小、颜色、透明度、hover状态、反转等IE8以上的浏览器都支持该技术。在使用IconFont之前你首先要确定你选则的字体库是否是收费。详细内容可以参考这篇文章图标字体化浅谈减少脚本与样式表的请求主要原则就是合并。在实际开发中我们遵循模块化的原则将代码分散到许多小文件中按照软件开发的原则这是完全正确的但对于上线页面来说每一个文件都会产生一个http请求严重影响性能。和css sprites一样将这些小文件合并到一个文件中可以减少http请求的数量并缩短最终用户响应时间。在合并过程中我们还需要使用工具精简移除不必要的字符以减小文件大小缩减下载时间和混淆除了移除不必要字符外还会改写源代码比如函数和变量名使用更短的标量名Javascript代码。对于采用AMD或CMD进行模块化开发的同学在合并过程中通常会将依赖的其他模块打包到一个文件中而模板html通常以字符串的方式内联到Javascript文件中。目前最常用的前端构建工具就是glup这里有一篇初步应用的文章前端 | gulp 打包 require.js 模块依赖2、页面内部优化关于页面内部优化主要方向样式表放在顶部、脚本文件放在底部、避免css表达式、把脚本的样式表放在外部、移除重复脚本关心性能的工程师都希望页面能否尽快的展现在用户面前对于页面中很多内容的页面我们都希望内容能够逐步加载为用户提供可视化回馈。而将样式表放在底部会导致浏览器阻止内容逐步呈现。为避免当页面变化时重绘页面元素浏览器会阻塞页面呈现直到样式表解析完毕详细内容可以查看我的这篇博客。所以如果将样式表放在顶部并不会减少资源的加载时间它减少的是页面的呈现时间。小米主页曾经犯过这样的错误将样式表放在底部会阻塞页面的逐步呈现而将script文件放在页面顶部同样会阻塞页面的逐步呈现。script元素会阻塞后续内容的解析因为script中可以同过document.write来更改页面。解决的办法就是将script标签放在页面底部。这样既可以让内容逐步呈现也可以提高下载的并行度。如果我们确定不需要document.write那可以为script标签加上asyn属性Ie中要加上defer提高并行下载度。CSS表达式是ie支持的可以用来动态更改css属性的一种方式我们不需要了解太多她的书写方式如下一旦在产品中发现expression关键字就要彻底消灭。使用外部脚本和样式这一条我想凡是有点经验的工程师都会这么干。移除重复脚本这条说的主要是避免在页面中多次加入同一份Javascript代码如果我们的开发中有依赖管理的方式比如AMD、CMD基本不会出现这种情况。3、启用缓存关于缓存的使用这里介绍两套方案expires/If-Modified-Since、Cache-Control/Etag前者是HTTP1.0中的缓存方案后者是HTTP1.1中缓存方案若http头部中同时出现二者后者的优先级更高。If-modified-since的方式通常被称为条件Get。浏览器缓存中保存了一个文件的副本但需要向服务器询问此副本是否可用。If-Modified-Since是浏览器将最后修改时间发送给服务器服务器相应头中Last-Modified进行对比若If-Modified-Since Last-Modified 则浏览器读取本地副本。此时响应状态为304 Not Modified, 并不在发送响应体。Expries虽然使用条件GET和304响应能够节省时间但浏览器跟服务器端仍然要发送一次请求进行确认。通过明确设置副本的过期时间可以避免条件GET。当浏览器发现响应头中的expires时会将过期时间和文件一起保存到缓存中去。在过期之前一直从缓存中读取。expires头使用一个特定的时间来指定缓存的有效期他要求浏览器与服务器时间完全一致。而且一旦过期服务器端配置中需要重新设顶一个过期时间。ETag实体标签是服务器用于检查浏览器缓存有效性的一种机制。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-ControlHTTP1.1引入了来代替Expires它使用max-age指令来指定副本被缓存多久该指令以秒为单位定义了一个更新窗组件从被请求开始到现在的秒数小于设定值则一直使用副本。避免了一次http请求。相比ExpriesCache-Control指令提供了更细粒度的控制。详细内容请看大额同学的文章透过浏览器看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查找、避免重定向CDNCDN是地理上分布的web server的集合用于更高效地发布内容。通常基于网络远近来选择给具体用户服务的web server。 这缩短了资源的传输响应时间有效提高web性能。DNS用于映射主机名和IP地址一般一次解析需要20120毫秒。浏览器会首先根据页面的主机名进行域名解析在有ISP返回结果之前页面不会加载任何内容所以减少DNS查找可以有效降低等待时间。为达到更高的性能DNS解析通常被多级别地缓存如由ISP或局域网维护的caching server本地机器操作系统的缓存如windows上的DNS Client Service浏览器。IE的缺省DNS缓存时间为30分钟Firefox的缺省缓冲时间是1分钟。 我们能做的是尽量减少一个页面的主机名但要在浏览器最大并行下载数跟dns查找之间做权衡。根据雅虎的研究最好将主机名控制在2-4个内。重定向将一个URL重新路由到另一个URL。重定向功能是通过301和302这两个HTTP状态码完成的如HTTP/1.1 301 Moved PermanentlyLocation: http://example.com/newuriContent-Type: text/html