前端性能优化35条规则 yahoo -服务器
前端性能优化35条规则 yahoo -服务器
前端性能优化35条规则 yahoo -服务器

01) 使用CDN

用户靠近您的Web服务器会影响响应时间。从用户的角度来看,跨多个地理位置分散的服务器部署您的内容将使您的页面加载速度更快。但是,您应该从哪里开始呢?

作为实现地理上分散的内容的第一步,请不要尝试重新设计Web应用程序以使其在分布式体系结构中工作。根据应用程序的不同,更改体系结构可能包括艰巨的任务,例如同步会话状态和跨服务器位置复制数据库事务。尝试缩短用户与您的内容之间的距离的尝试可能会因此应用程序体系结构步骤而被延迟或永远不会过去。

请记住,最终用户响应时间的80-90%是花在下载页面上的所有组件上的:图像,样式表,脚本,Flash等。这是性能的黄金法则。与其从重新设计应用程序体系结构这一艰巨的任务开始,不如先分散静态内容,这是更好的选择。这不仅可以大大缩短响应时间,而且由于内容传送网络的原因,它更容易实现。

内容交付网络(CDN)是分布在多个位置的Web服务器的集合,目的是将内容更有效地交付给用户。选择用于向特定用户传送内容的服务器通常基于网络邻近性的度量。例如,选择网络跳数最少的服务器或响应时间最快的服务器。

一些大型的互联网公司拥有自己的CDN,但是使用CDN服务提供商(例如Akamai TechnologiesEdgeCastlevel3)具有成本效益。对于初创公司和私人网站,CDN服务的成本可能令人望而却步,但是随着您的目标受众越来越大并变得更加全球化,为了实现快速响应,CDN是必不可少的。在Yahoo!上,将静态内容从其应用程序Web服务器移至CDN(如上所述的第三方和Yahoo自己的CDN)的属性将最终用户的响应时间缩短了20%或更多。切换到CDN是相对容易的代码更改,它将显着提高网站的速度

02) 添加ExpiresCache-Control响应头

该规则有两个方面:

  • 对于静态组件:通过设置远期Expires头文件来实现“永不过期”策略
  • 对于动态组件:使用适当的Cache-Control标头来帮助浏览器进行条件请求

网页设计越来越丰富,这意味着页面中将包含更多脚本,样式表,图像和Flash。首次访问您的页面的访问者可能必须发出多个HTTP请求,但是通过使用Expires标头,您可以使这些组件可缓存。这避免了后续页面视图上不必要的HTTP请求。Expires标头最常与图像一起使用,但应在所有组件(包括脚本,样式表和Flash组件)上使用它们。

浏览器(和代理)使用缓存来减少HTTP请求的数量和大小,从而使网页加载速度更快。Web服务器使用HTTP响应中的Expires标头来告诉客户端可以将组件缓存多长时间。这是一个远期的Expires标头,告诉浏览器直到2010年4月15日,此响应才会陈旧。

1
过期:格林尼治标准时间2010年4月15日星期四20:00:00

如果您的服务器是Apache,请使用ExpiresDefault指令设置相对于当前日期的到期日期。此ExpiresDefault伪指令示例将Expires日期设置为从请求时间算起的10年。

1
过期默认为“访问权限加上10年”

请记住,如果使用远期的Expires标头,则每当组件更改时,都必须更改组件的文件名。在雅虎!我们通常将此步骤作为构建过程的一部分:版本号嵌入在组件的文件名中,例如yahoo_2.0.6.js。

仅在用户已经访问您的网站之后,使用将来有效的Expires标头才会影响页面浏览量。当用户首次访问您的站点并且浏览器的缓存为空时,它对HTTP请求的数量没有影响。因此,此性能改进的影响取决于用户使用预填充缓存访问您的页面的频率。(“主缓存”已经包含了页面中的所有组件。)我们在Yahoo!上进行了测量。并发现带有预填充缓存的页面浏览量为75-85%。通过使用远期的Expires标头,您可以增加浏览器缓存的组件数量,并在后续的页面视图中重新使用这些组件,而无需通过用户的Internet连接发送单个字节。

03) 启用Gzip

通过前端工程师的决定,可以大大减少在网络上传输HTTP请求和响应所花费的时间。的确,最终用户的带宽速度,Internet服务提供商,与对等交换点的距离等等,都是开发团队无法控制的。但是还有其他影响响应时间的变量。压缩通过减小HTTP响应的大小来减少响应时间。

从HTTP / 1.1开始,Web客户端使用HTTP请求中的Accept-Encoding标头指示对压缩的支持。

1
Accept-Encoding: gzip, deflate

如果Web服务器在请求中看到此标头,则可以使用客户端列出的方法之一压缩响应。Web服务器通过响应中的Content-Encoding标头将其通知给Web客户端。

1
Content-Encoding: gzip

Gzip是目前最流行,最有效的压缩方法。它由GNU项目开发,并由RFC 1952标准化。您可能会看到的唯一其他压缩格式是deflate,但效率不高且不那么受欢迎。

压缩通常会将响应大小减少约70%。如今,大约90%的Internet流量是通过声称支持gzip的浏览器传输的。如果使用Apache,则配置gzip的模块取决于您的版本:Apache 1.3使用mod_gzip,而Apache 2.x使用mod_deflate

浏览器和代理存在一些已知问题,可能会导致浏览器的预期内容与压缩内容接收不匹配。幸运的是,随着使用较旧的浏览器的减少,这些边缘情况正在减少。Apache模块通过自动添加适当的Vary响应标头来提供帮助。

服务器根据文件类型选择要gzip的内容,但通常在决定压缩内容方面受限制。大多数网站都将其HTML文档压缩为gzip。gzip您的脚本和样式表也是值得的,但是许多网站都错过了这个机会。实际上,压缩任何文本响应(包括XML和JSON)都是值得的。图片和PDF文件不应压缩,因为它们已经被压缩。尝试对它们进行gzip压缩不仅浪费CPU,而且可能会增加文件大小。

压缩尽可能多的文件类型是减轻页面重量并加快用户体验的简便方法。

04) 配置Etag

实体标记(ETag)是Web服务器和浏览器用来确定浏览器缓存中的组件是否与原始服务器上的组件匹配的一种机制。(“实体”是“组件”的另一个词:图像,脚本,样式表等。)添加了ETag,以提供一种用于验证实体的机制,该机制比上次修改的日期更灵活。ETag是一个字符串,用于唯一标识组件的特定版本。唯一的格式限制是用引号将字符串引起来。原始服务器使用ETag响应标头指定组件的ETag 。

1
2
3
4
HTTP/1.1 200 OK
Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
ETag: "10c24bc-4ab-457e1c1f"
Content-Length: 12195

以后,如果浏览器必须验证组件,它将使用If-None-Match标头将ETag传递回原始服务器。如果ETag匹配,则返回304状态代码,此示例将响应减少12195字节。

1
2
3
4
5
GET /i/yahoo.gif HTTP/1.1
Host: us.yimg.com
If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT
If-None-Match: "10c24bc-4ab-457e1c1f"
HTTP/1.1 304 Not Modified

ETag的问题在于,通常使用使它们对托管站点的特定服务器而言是唯一的属性来构造它们。当浏览器从一台服务器获取原始组件,然后尝试在另一台服务器上验证该组件时,ETag将不匹配,这种情况在使用服务器集群处理请求的网站上非常普遍。默认情况下,Apache和IIS都将数据嵌入到ETag中,从而大大降低了在具有多台服务器的网站上成功进行有效性测试的几率。

Apache 1.3和2.x的ETag格式为inode-size-timestamp。尽管一个给定的文件可能位于多个服务器的同一目录中,并且具有相同的文件大小,权限,时间戳等,但它的索引节点在一个服务器和另一个服务器之间是不同的。

IIS 5.0和6.0的ETag存在类似问题。IIS上ETag的格式为Filetimestamp:ChangeNumber。AChangeNumber是一个计数器,用于跟踪对IIS的配置更改。ChangeNumber在网站后面的所有IIS服务器中,这不太可能是相同的。

最终结果是,Apache和IIS为完全相同的组件生成的ETag从一台服务器到另一台服务器将不匹配。如果ETag不匹配,则用户不会收到ETag设计用于的小而快速的304响应。相反,他们将获得正常的200响应以及该组件的所有数据。如果您将网站托管在仅一台服务器上,那么这不是问题。但是,如果您有多个服务器托管您的网站,并且您使用默认ETag配置的Apache或IIS,则用户的页面访问速度将变慢,服务器的负载将增加,带宽消耗将增加,而代理服务器将不再高效地缓存您的内容。即使您的组件具有将来的Expires标头,只要用户单击“重新加载”或“刷新”,仍会发出条件GET请求。

如果您没有利用ETag提供的灵活验证模型,最好完全删除ETag。在Last-Modified基于组件的时间戳头进行验证。删除ETag会减少响应和后续请求中HTTP标头的大小。此Microsoft支持文章介绍了如何删除ETag。在Apache中,只需将以下行添加到Apache配置文件中即可完成此操作:

1
FileETag none

05) 尽早输出(flush)缓冲

当用户请求页面时,后端服务器将HTML页面拼接在一起可能需要200到500毫秒的时间。在这段时间内,浏览器在等待数据到达时处于空闲状态。在PHP中,您可以使用函数flush()。它允许您将部分就绪的HTML响应发送到浏览器,以便浏览器可以在后端忙于处理HTML页面的其余部分时开始获取组件。好处主要体现在繁忙的后端或轻量级的前端上。

考虑在头之后紧跟着刷新的一个好地方,因为头的HTML通常更易于生成,并且它允许您包括任何CSS和JavaScript文件,以便浏览器在后端仍在处理时开始并行获取。

例子:

1
2
3
4
5
	... <!-- css, js -->
</head>
<?php flush(); ?>
<body>
... <!-- content -->

06) Ajax请求尽量使用GET方法

雅虎 邮件团队发现,使用时XMLHttpRequest,POST在浏览器中实现为两个步骤:首先发送标头,然后发送数据。因此,最好使用GET,它只需要发送一个TCP数据包即可(除非您有很多Cookie)。IE中的最大URL长度为2K,因此,如果您发送的数据超过2K,则可能无法使用GET。

一个有趣的副作用是,没有实际发布任何数据的POST行为就像GET。基于HTTP规范,GET是用于检索信息的,因此(仅在语义上)在仅请求数据时使用GET(而不是将数据发送到服务器端存储)是有意义的。

07) 避免图片src为空

图像出现的次数超过预期。它以两种形式出现:

  1. straight HTML

  2. JavaScript

    var img = new Image();
    img.src = “”;

两种形式都会产生相同的效果:浏览器再次向您的服务器发出请求。

  • Internet Explorer向页面所在的目录发出请求。
  • Safari和Chrome会向实际页面发出请求。
  • Firefox 3和更早版本的行为与Safari和Chrome相同,但版本3.5解决了此问题[bug 444931],并且不再发送请求。
  • 遇到空图像src时,Opera不会执行任何操作。

为什么这种行为不好?

  1. 通过发送大量意外流量来破坏服务器,特别是对于每天获得数百万次页面查看的页面。
  2. 浪费的服务器计算周期生成了永远不会被查看的页面。
  3. 可能损坏了用户数据。如果您正在通过Cookie或其他方式跟踪请求中的状态,则可能会破坏数据。即使图像请求未返回图像,浏览器也会读取并接受所有标头,包括所有cookie。当其余的响应被丢弃时,损坏可能已经造成。

此行为的根本原因是在浏览器中执行URI解析的方式。RFC 3986-统一资源标识符中定义了此行为。当遇到空字符串作为URI时,它被视为相对URI,并根据5.2节中定义的算法进行解析。此特定示例(一个空字符串)在5.4节中列出。Firefox,Safari和Chrome均按照规范正确解析了一个空字符串,而Internet Explorer则不正确地解析了该字符串,这显然符合规范RFC 2396-统一资源标识符的较早版本(RFC 3986已弃用) 。因此,从技术上讲,浏览器正在执行解析相对URI的工作。问题在于,在这种情况下,

HTML5在标记的src属性的描述中添加了内容,以指示浏览器不要在第4.8.2节中提出额外的请求:

src属性必须存在,并且必须包含一个有效的URL,该URL引用既非分页也没有脚本化的非交互式,可选动画的图像资源。如果元素的基本URI与文档的地址相同,则src属性的值不能为空字符串。

希望将来浏览器不会出现此问题。不幸的是,对于