本书2008年出版,有些内容显得有些老了,很多优化已经被广泛应用甚至有了更好的优化方式,但是阅读后仍然获益良多。
绪言A :前端性能的重要性
时间花在哪了?(性能黄金法则)
- 至少80%的最终用户响应时间花在了下载页面中所有组件上,仅10%-20%的时间用来下载HTML文档
绪言B :HTTP概述
- 压缩:用压缩减小响应的大小,服务器用Content-Encoding头确认响应已被压缩
- 条件get请求:浏览器缓存的副本,用Last-Modified头使浏览器知道组件最后修改时间,服务器会返回304响应
- Expires:明确指出浏览器是否可以使用组件的缓存副本,它会和过期时间组件一起保存到缓存中
- Keep-Alive:持久连接的引入解决了多对一请求服务器导致的socket连接低效性的问题
规则1 :减少HTTP请求
- 图片地图:通过点击图片的位置确认目标url(通过合并图片减少HTTP请求)
- Css Spirites(雪碧图)
合并后的图片比分离的图片的总和要小,这是因为它降低了图片自身的开销(颜色表,格式信息,等)
- 内联图片:通过data:URL模式可以在web页面中包含图片但无需任何额外的HTTP请求;将其放置在外部样式表中会增加一个额外的HTTP请求,但是可以被缓存
- 合并脚本和样式表
规则2:使用内容发布网络(CDN)
- cdn是一组分布在不同地理位置的Web服务器,原理是服务器里用户更近,HTTP请求响应时间将缩短
- cdn还可以节省成本,可能选择网络阶跃数最小的服务器,或者具有最短响应的服务器
- cdn缺点:1. 响应时间受到其他网站流量的影响;2. 无法直接控制组件服务器带来的特殊麻烦,比如修改HTTP响应头;3. 如果CDN服务的性能下降了,你的工作质量也随之下降
规则3 :添加Expires头
Expires: Thu, 15 Apr 2010 20:00:00 GMT Expires头严格要求服务器和客户端时钟严格同步的问题,过期后还需要在服务器配置中提供一个新的日期
- Max-Age和mode_expires:可以消除Expires的限制;如果两者同时出现,max-age指令将重写Expires头
- 空缓存VS完整缓存:通过长久的Expires头可以增加被浏览器缓存的组件的数量
- 不仅仅是图片:长久的Expires头应该包含任何不经常变换的组件,包括脚本、样式表和Flash组件,但不包含HTML文档
- 修改文件名:版本号嵌在组件文件名中
规则4:压缩组件
- 压缩脚本和样式表
- 平衡压缩和代理支持,需要在加快响应时间、减小带宽开销和边缘情形浏览器缺陷之间进行权衡
规则5 :将样式表放在顶部
- 逐步呈现:将样式表放在底部会导致在浏览器中阻止内容逐步呈现,导致白屏(性能主要是用户的感受,在一定程度上,用户并不care组件加载时间)
- 使用LINK标签替代@import会带来性能上的收益,@import会导致组件加载的无序性
- 样式表在页面中并不影响下载时间,但会影响页面的呈现;如果样式表放在后面,可能会导致无样式内容闪烁,白屏是对其的弥补
- 使用LINK标签将样式表放在文档的HEAD中
规则6 :将脚本放在底部
脚本下载后立即执行,这就阻止了并行下载和html加载,因此脚本越靠下,越多内容能够逐步呈现
- 并行下载:过多的并行下载会阻止浏览器性能
- 脚本阻塞后面内容呈现,阻塞对后面组件下载
规则7 :避免CSS表达式
规则8 :使用外部JavaScript和CSS
- 纯粹而言内联比外置快一点,然而不能被缓存;因此网站能够为用户提供高缓存率时,外置的收益更大
- 组件重用:JS和CSS外部文件的边界影响组件重用程度,因此主页更适合内联样式的写法
- 两全其美:加载后下载(通常将组件放在一个不可见的Iframe中)、动态内联(通过cookie判断)
规则9:减少DNS查找
DNS将主机名映射到Ip地址上,可以将多个Ip地址关联到一个主机名,为网站提高冗余度
- DNS缓存和TTL(存活时间):应该周期性地清除缓存中的DNS记录,并且通过大量不同的配置检测清除的频率有多高
- HTTP协议中Keep-Alive特性可以同时覆盖TTL和浏览器的时间消耗,因此浏览器和Web服务器正在保持通信,并保持TCP连接打开状态,就不会进行DNS查找
- TTL值建议值1天
- 减少唯一主机名数量就可以减少DNS查找数量:当客户端DNS为空时,DNS查找数量可Web页面中唯一主机名数量相同
- 通过使用Kepp-Alive和较少域名减少DNS查找
规则10:精简JavaScript
- 精简:从代码移除不必要的字符以减少其大小,所有注释和不必要的空白字符都会被移除,可以降低响应时间
-
- 混淆:移除注释和空白之外,将函数和变量的名字转换为更短的字符串(可能会引起缺陷)
- 节省:减小了文件大小
规则11:避免重定向
- 重定向的类型:3xx状态码(304用来响应条件get请求,避免下载已经存在浏览器的数据)
- 重定向如何损伤性能?:延迟了整个HTTP文档的传输
- 重定向之外的其他选择:缺少结尾斜线;连接网站;跟踪内部流量;跟踪出站流量;优化URL
规则12:移除重复脚本
导致脚本重复的两个主要因素:团队大小和脚本数量
- 重复脚本损伤性能:不必要的HTTP请求和执行JS所浪费的时间,多次求值,导致网页变慢
- 避免重复脚本:实现脚本管理模块,需要添加处理脚本依赖性和版本的功能
规则13:配置ETag
实体标签(ETag)是Web服务器和浏览器用于确认缓存组件的有效性的一种机制(标识组件特定版本的字符串)。 服务器在检测缓存的组件是否和原始服务器上的组件相匹配时有两种方式:比较最新修改日期、比较实体标签
- 最新修改日期:原始服务器通过Last-Modified响应头来返回组件的最新修改日期
- 实体标签:实体是之前组件的另一种称呼,ETag比最新修改日期更灵活;使用If-None-Match头将ETag传回原始服务器,如果匹配,就会返回304状态码
- ETag缺陷:1. 不同服务器完全相同的ETag不匹配,对于服务器集群会导致性能的下降;2. 降低了代理缓存的效率
- ETag用还是不用:如果组件必须通过最新修改日期之外的一些东西来验证,ETag是一种强大的方法;否则,最好简单的将其移除。
规则14:使用Ajax可缓存
- Web2.0、DHTML和Ajax
- 异步与即时(主动请求和被动请求)
- 优化Ajax请求:最重要的方式是缓存。其中 规则4(压缩组件)、规则9(减少DNS查找)、规则10(精简JavaScript)、规则11(避免重定向)、规则13(ETag)也适用
- 确保Ajax请求遵守性能指导,尤其应具有长久的Expires头
|