1.尽量减少HTTP请求数
80%的终端用户响应时间都花在了前端上,其中大部分时间都在下载页面上的各种组件:图片,样式表,脚本,Flash等等。减少组件数必然能够减少页面提交的HTTP请求数。这是让页面更快的关键。
减少页面组件数的一种方式是简化页面设计。但有没有一种方法可以在构建复杂的页面同时加快响应时间呢?嗯,确实有鱼和熊掌兼得的办法。
合并文件是通过把所有脚本放在一个文件中的方式来减少请求数的,当然,也可以合并所有的CSS。如果各个页面的脚本和样式不一样的话,合并文件就是一项比较麻烦的工作了,但把这个作为站点发布过程的一部分确实可以提高响应时间。
CSS Sprites是减少图片请求数量的首选方式。把背景图片都整合到一张图片中,然后用CSS的background-image和background-position属性来定位要显示的部分。
图像映射可以把多张图片合并成单张图片,总大小是一样的,但减少了请求数并加速了页面加载。图片映射只有在图像在页面中连续的时候才有用,比如导航条。给image map设置坐标的过程既无聊又容易出错,用image map来做导航也不容易,所以不推荐用这种方式。
行内图片(Base64编码)用data: URL模式来把图片嵌入页面。这样会增加HTML文件的大小,把行内图片放在(缓存的)样式表中是个好办法,而且成功避免了页面变“重”。但目前主流浏览器并不能很好地支持行内图片。
减少页面的HTTP请求数是个起点,这是提升站点首次访问速度的重要指导原则。
2、减少DNS查找
DNS就像电话簿将人们的姓名映射到他们的电话号码一样,当您输入www.yahoo.com时,浏览器会通过DNS解析返回服务器的IP地址,这个DNS解析过程需要成本,通常需要20-120ms才能解析成功,在这之前,浏览器无法从服务器获取任何内容。
通过缓存DNS查找来获得更好的性能。DNS信息保留在操作系统的DNS缓存中,大多数的浏览器都有自己的缓存,与操作系统的分开。
默认情况,IE会将DNS查找缓存30分钟,FireFox缓存一分钟。
当客户端的DNS缓存为空(对于浏览器和操作系统)时,DNS查找的数量等于网页中唯一主机名的数量。 减少唯一主机名的数量可减少DNS查找的数量。
减少唯一主机名的数量有可能减少页面中发生的并行下载量。避免DNS查找会缩短响应时间,但减少并行下载可能会缩短响应时间。 准则是将这些组件分成至少两个但不超过四个主机名。这是减少DNS查找和允许高度并行下载之间的良好折衷。
3、让Ajax可缓存
Ajax的一个好处是可以给用户提供即时反馈,因为它能够从后台服务器异步请求信息。然而,用了Ajax就无法保证用户在等待异步JavaScript和XML响应返回期间不会非常无聊。在很多应用程序中,用户能够一直等待取决于如何使用Ajax。例如,在基于web的电子邮件客户端中,用户为了寻找符合他们搜索标准的邮件消息,将会保持对Ajax请求返回结果的关注。重要的是,要记得“异步”并不意味着“即时”。
要提高性能,优化这些Ajax响应至关重要。最重要的提高Ajax性能的方法就是让响应变得可缓存,就像在添上Expires或者Cache-Control HTTP头中讨论的一样。下面适用于Ajax的其它规则:Gzip组件、减少DNS查找、压缩JavaScript、避免重定向、配置ETags。
4、避免重定向
使用301和302状态码完成重定向。下面是一个301响应http头示例:
HTTP/1.1 301 Moved Permanently
Location: http://example.com/newuri
Content-Type: text/html
浏览器自动将用户带到Location字段指定的URL。跳转所需的所有信息都在http头 ,响应的主体通常是空的。301或302响应一般不会被缓存,除非有Expires 或者Cache-Control 指定要缓存。
要记住的主要事情是重定向会降低用户体验。在用户和HTML文档之间插入重定向会延迟页面中的所有内容,因为页面中的任何内容都无法呈现,并且在HTML文档到达之前不会开始下载任何组件。
最浪费的重定向之一经常发生,就是在URL中缺少尾部/ 会产生301响应
5、延迟加载组件
可以凑近看看页面并问自己:什么才是一开始渲染页面所必须的?其余内容都可以等会儿。
JavaScript是分隔onload事件之前和之后的一个理想选择。例如,如果有JavaScript代码和支持拖放以及动画的库,这些都可以先等会儿,因为拖放元素是在页面最初渲染之后的。其它可以延迟加载的部分包括隐藏内容(在某个交互动作之后才出现的内容)和折叠的图片。
工具可帮你减轻工作量:YUI Image Loader可以延迟加载折叠的图片,还有YUI Get utility是一种引入JS和CSS的简单方法。Yahoo!主页就是一个例子,可以打开Firebug的网络面板仔细看看。
最好让性能目标符合其它web开发最佳实践,比如“渐进增强”。如果客户端支持JavaScript,可以提高用户体验,但必须确保页面在不支持JavaScript时也能正常工作。所以,在确定页面运行正常之后,可以用一些延迟加载脚本增强它,以支持一些拖放和动画之类的华丽效果。
6、预加载组件
预加载看起来和延迟加载相反,但它实际上有着不同的目标,通过预加载组件,您可以利用浏览器空闲的时间并请求将来需要的组件(如图像,样式和脚本)。这样,当用户访问下一页时,您可以将大部分组件放在缓存中,并且用户加载页面将更快。
有几种预加载类型:
无条件预加载:一旦onload触发,你立即获取另外的组件。比如谷歌会在主页这样加载搜索结果页面用到的雪碧图。
有条件预加载:基于用户操作,您可以进行有根据的猜测,即用户前进的位置并相应地预加载。
预期的预加载:在旧网页预加载新网页的部分组件,那么切换到新网页时就不会是没有任何缓存了。
7、减少DOM数量
复杂页面意味着要下载更多字节,这也意味着JavaScript中的DOM访问速度更慢。例如,当您想要添加事件处理程序时,如果在页面上循环遍历500或5000个DOM元素,则会有所不同。
8、跨域拆分组件
拆分组件来达到最大化的并行下载,由于DNS查询的副作用,最好保证使用的域名不准超过2-4个。例如,您可以托管HTML和动态内容,www.example.org 并在static1.example.org和之间拆分静态组件。
9、 最少的iframe
iframe允许html文档被插入到父文档。
<iframe>优点:帮助解决缓慢的第三方内容的加载,如广告和徽章、安全沙盒、并行下载脚本
<iframe>缺点:
即使空的也消耗(资源和时间)、阻塞了页面的onload、非语义化(标签)
10、优化图片
尝试把GIF格式转换成PNG格式,看看是否节省空间。在所有的PNG图片上运行pngcrush(或者其它PNG优化工具)
根据不同终端,切不同格式不同分辨率大小的图,如png8 png24 gif jpg等(附加)
美工设计,电脑端设计建议宽1920以上,移动端以iphone6尺寸为基础保证失真率最小 750画布(附加)
根据不同屏幕大小。media query调用不同尺寸的图片
11、把组件放在不含cookie的域下
当浏览器发送对静态图像的请求时,cookie也会一起发送,而服务器根本不需要这些cookie。所以它们只会造成没有意义的网络通信量,应该确保对静态组件的请求不含cookie。可以创建一个子域,把所有的静态组件都部署在那儿。
如果域名是www.example.org,可以把静态组件部署到static.example.org。然而,如果已经在顶级域example.org或者www.example.org设置了cookie,那么所有对static.example.org的请求都会含有这些cookie。这时候可以再买一个新域名,把所有的静态组件部署上去,并保持这个新域名不含cookie。Yahoo!用的是yimg.com,YouTube是ytimg.com,Amazon是images-amazon.com等等。
把静态组件部署在不含cookie的域下还有一个好处是有些代理可能会拒绝缓存带cookie的组件。有一点需要注意:如果不知道应该用example.org还是www.example.org作为主页,可以考虑一下cookie的影响。省略www的话,就只能把cookie写到*.example.org,所以因为性能原因最好用www子域,并且把cookie写到这个子域下。
12、跨域分离组件
分离组件可以最大化并行下载,但要确保只用不超过2-4个域,因为存在DNS查找的代价。例如,可以把HTML和动态内容部署在www.example.org,而把静态组件分离到static1.example.org和static2.example.org。
13、把样式表放在顶部
在Yahoo!研究性能的时候,我们发现把样式表放到文档的HEAD部分能让页面看起来加载地更快。这是因为把样式表放在head里能让页面逐步渲染。
关注性能的前端工程师想让页面逐步渲染。也就是说,我们想让浏览器尽快显示已有内容,这在页面上有一大堆内容或者用户网速很慢时显得尤为重要。给用户显示反馈(比如进度指标)的重要性已经被广泛研究过,并且被记录下来了。在我们的例子中,HTML页面就是进度指标!当浏览器逐渐加载页面头部,导航条,顶部logo等等内容的时候,这些都被正在等待页面加载的用户当作反馈,能够提高整体用户体验。
14、保持组件小于25K
此限制与iPhone不会缓存大于25K的组件这一事实有关。请注意,这是未压缩的大小。在这里减少组件大小很重要,因为单独使用gzip可能还不够。
15、将组件打包到多部分文档中
将组件打包到多部分文档就像带有附件的电子邮件,它可以帮助您通过一个HTTP请求获取多个组件(请记住:HTTP请求很昂贵)。使用此技术时,首先检查用户代理是否支持它(iPhone不支持)。