原文地址:http://developer.yahoo.com/performance/rules.html
本文在尊重原文基础上,尽量翻译得通俗易懂一些。
本文内容
- 提高 Web 站点性能的最佳实践
- 最大限度减少 HTTP 请求
- 使用内容分发网络(CDN)
- 添加 Expires 或 Cache – Control 头
- Gzip 组件
- CSS 放在页面顶部
- JavaScript 放在页面底部
- 避免 CSS 表达式
- 使用外部 JavaScript 和 CSS
- 减少 DNS 查询
- 精简 JavaScript 和 CSS
- 避免重定向
- 删除重复的脚本
- 配置 ETags
- 使得 Ajax 可缓存
- 尽早强制地发送缓冲给客户端
- 用 GET 发送 Ajax 请求
- 延迟加载组件
- 预加载组件
- 减少 DOM 元素数量
- 根据域名划分页面内容
- 最小化 iframe 数量
- 不要出现 404 错误
- 减小 Cookie 的大小
- 对组件使用无 coockie 域名
- 最小化 DOM 访问
- 开发智能的事件处理程序
- 用 <link> 代替 @import
- 避免使用滤镜
- 优化图像
- 优化 CSS Sprites
- 不要在 HTML 中缩放图像
- favicon.ico 要小且可缓存
- 保持组件 25K 以下
- 把组件打包到一个 Multipart 文档
- 避免图片 src 属性为空
- 修改记录
下面是使页面更快的35个最佳实践,它们被划分为7个类别。
类别: content、server、cookie、css、javascript、images、mobile
(Yahoo 开发的浏览器插件 YSLOW,利用这七个类作为评价页面的指标)
最大限度减少 HTTP 请求
类别: content
最终用户(the end-user)80%的响应时间花费在前端(the front-end)。大部分时间用来下载页面中的所有组件:图像、CSS、JS、Flash 等。因此,反过来,减少页面组件的数量,就可以减少渲染(呈现)页面所需的 HTTP 请求的数量。这是加快页面的关键。
一个方法当然是简化页面设计,减少页面组件的数量。但是否有方法,既构建具有丰富内容的网页,也实现了快速响应?下面是减少 HTTP 请求数量的技巧,也提供了丰富的网页设计。
- 合并文件。通过把所有脚本或 CSS 合并到一个单独的文件,来减少 HTTP 请求的数量。当在不同的页面中,脚本和 CSS 都不太一样时,合并就比较困难。你可以把合并放到最后部署时,从而改进响应时间。
- CSS 精灵(CSS Sprites)。CSS Sprites是减少图像请求数量的首选方法。把你的背景图像合并到一个单独的图像,并且使用CSS 的“background-image”和“background-position”属性,来显示你所需的图像部分。
CSS Sprites 是一种 CSS 图像拼合技术,一种网页图片应用处理方式。
- 图像地图(Image maps)。把多个图像合并到一个单独的图像。合并前与合并后的图像总体大小相同,而且减少了HTTP请求的数量,加快了页面速度。但只有当图像在页面中是连续的,Image maps才好用,如导航栏。定义图像地图的坐标很枯燥,而且容易出错。对导航使用图像地图不具有可访问性,所以不推荐。
- 内嵌图片(Inline images)。在页面中,使用 data: URL scheme 嵌入图像数据。这会增加页面大小。Inline images 与 CSS(已缓存)相结合可以减少 HTTP 请求,避免增加页面大小。目前,所有主流浏览器尚不支持 Inline images。
减少页面的HTTP请求的数量首选要做的事,对于改善用户初次访问页面的性能,这是最重要准则。正如 Tenni Theurer 在其文章 Browser Cache Usage - Exposed! 指出的,每天访问你网站的 40-60% 人都是无缓存的(都是初次访问,无本地缓存)。使页面对初次访问更快,是更好的用户体验的关键。这些首次访问者的页面快速更好的用户体验是关键。
批注
一个页面往往包含很多资源,比如图像、JS、CSS 等,而这些资源都在服务器上,客户端若想显示这个页面,必须通过网络从服务器下载资源到本地。可想而知,虽然每个资源都很小,也就在几十 K 左右,但是数量很多,客户端每次需要这样资源,都会到服务器上下载,因此,减少下载的次数,或是下载完后,直接从浏览器缓存里获得,将很有意义。
本节的技巧:合并文件、CSS Sprites、Image maps、Inline images 都是为了减少下载次数。比如,如果一个页面需要三个 CSS,那么在用户初次访问页面时,需要向服务器请求三次。因此,若将这三个 CSS 合并成一个,那么只需下载一次;图像也是如此,一个页面最多的就是图像,试想网站的导航条,与其为每个操作都搞一个图片,倒不如将这些图片合并在一个图像上,再通过 CSS 获得图片局部区域。
使用内容分发网络(CDN)
类别: server
用户“接近”你Web服务器的程度会影响响应时间。把内容部署在多个、地理位置分散的服务器上,会使页面加载的速度从用户角度看更快。但是我们应该从哪里开始?
作为实现地理位置分散内容的第一步,不要试图重新设计你的Web应用程序,使它运行在一个分布式的结构中。根据应用程序,改变结构,包括跨服务器同步会话状态和复制数据库事务等,这些艰巨的任务。根据不同的应用,改变结构可以包括跨服务器的位置同步会话状态和复制数据库交易等艰巨任务。尝试减少用户和内容之间的距离,可以延迟,或从不通过,这是应用程序结构的步骤。
记住,最终用户的80-90% 响应时间花费在下载所有页面的组件:图像、CSS、JS、Flash 等,这是提高性能的黄金法则。最好先分散你的静态内容,如图像、CSS、JS、Flash 等,而不是重新设计应用程序结构艰巨的工作开始。由于内容发布网络,不仅大幅度减少了响应时间,而且简化了应用程序。
一个 CDN 是一个处于多个位置的 Web 服务器的集合,更有效地向用户发送内容。选择哪个服务器发送内容给特定用户通常是基于一个网络评估。例如,选择最少的网络跳数或最快的响应时间。
一些大型的互联网公司拥有自己的 CDN,而通过 CDN 服务提供商,如 Akamai Technologies, EdgeCast 或 level3,成本则很高。对于刚成立的公司和私人站点,一个 CDN 服务的成本可以让人望而却步,但当你越来越受关注,并全球化时,一个 CDN 是必需的,以便快速响应。以 Yahoo! 为例,他们把静态内容从应用程序中移到 CDN(上面提到 CDN 服务提供商,以及他们自己的 CDN)上,提高了最终用户 20% 以上的响应时间。使用 CDN 是一个只需要相对简单地修改代码,显著改善站点速度的方法。
批注
客户端访问服务器,要经过路由,是要计算代价的,最小跳数也好,最少响应时间也罢,所以将自己的网站内容部署在多个地理位置是有必要的。
添加 Expires 或 Cache – Control 头
类别: server
此规则有两个方面:
- 对于静态组件:设置 Expires 头为 "Never expire" 策略——“永不过期”;
- 对于动态组件:使用适当的 Cache – Control 头,帮助浏览器有条件地发送请求。
随着页面越来越丰富,这意味着更多的 JS、CSS、图像和 Flash。一个初次访问页面的用户会发出很多 HTTP 请求,但是通过 Expires 头,你可以使那些组件被浏览器缓存。在之后的页面浏览,就避免了不必要的 HTTP 请求。Expires 头经常用在图像,但也可以用在包括 JS、CSS 和 Flash 所有组件。
浏览器(和代理)使用缓存来减少 HTTP 请求的次数和规模,使页面加载速度更快。一个 Web 服务器在 HTTP 响应中使用 Expires 头,会告诉客户端这个组件被缓存多长时间。下面 Expires 头告诉浏览器,这个响应直到 2011年4月15日 都是可靠的。