##加速网站的最佳做法

最小化HTTP请求

最终用户响应时间的80%用于前端。大多数时间都与下载页面中的所有组件有关:图像,样式表,脚本,Flash等。减少组件的数量又减少了呈现页面所需的HTTP请求的数量。这是加快页面速度的关键。

减少页面中组件数量的一种方法是简化页面的设计。但是,有没有一种方法可以构建具有更丰富内容的页面,同时又可以实现快速响应时间?这里有一些减少HTTP请求数量的技术,同时仍然支持丰富的页面设计。

合并文件是一种通过将所有脚本合并为一个脚本,并类似地将所有CSS合并为一个样式表来减少HTTP请求数量的方法。当脚本和样式表在页面之间变化时,组合文件更具挑战性,但是将其作为发布过程的一部分可以缩短响应时间。

CSS Sprite是减少图像请求数量的首选方法。将背景图像合并为单个图像,并使用CSSbackground-image和background-position属性显示所需的图像段。

图像映射将多个图像合并为一个图像。整体大小大致相同,但是减少HTTP请求的数量可以加快页面的速度。图像映射仅在图像在页面中是连续的时才有效,例如导航栏。定义图像地图的坐标可能很乏味且容易出错。也无法使用图像地图进行导航,因此不建议使用。

内联图像使用data:URL方案将图像数据嵌入到实际页面中。这会增加HTML文档的大小。将内嵌图像合并到(缓存的)样式表中是减少HTTP请求并避免增加页面大小的一种方法。所有主流浏览器尚不支持嵌入式图像。

开始减少页面中的HTTP请求数。这是提高初次访问者性能的最重要指南。正如Tenni Theurer的博客文章《浏览器缓存使用情况-公开!,有40-60%的每日访问者访问您的网站时会出现空的缓存。使这些初次访问者快速浏览您的页面对于改善用户体验至关重要。

使用内容交付网络

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

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

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

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

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

添加过期或缓存控制标头

该规则有两个方面:

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

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

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

  过期:星期四,2010年4月15日20:00:00 GMT

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

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

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

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

Gzip组件

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

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

  接受编码:gzip,放气

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

  内容编码: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,而且可能会增加文件大小。

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

将样式表放在顶部

虽然研究在雅虎的表现!我们发现,移动样式表文件HEAD使页面看起来是加载速度更快。这是因为将样式表放在HEAD中可以使页面逐步呈现。

关心性能的前端工程师希望页面逐渐加载。也就是说,我们希望浏览器尽快显示其具有的所有内容。这对于内容丰富的页面以及Internet连接速度较慢的用户而言尤其重要。为用户提供视觉反馈(例如进度指示器)的重要性已经得到了充分的研究和记录。在我们的例子中,HTML页面是进度指示器!当浏览器逐步加载页面时,标题,导航栏,顶部的徽标等均作为等待页面的用户的视觉反馈。这样可以改善整体用户体验。

将样式表放在文档底部附近的问题是,它禁止在许多浏览器(包括Internet Explorer)中进行渐进式渲染。这些浏览器会阻止渲染,以避免样式改变时不得不重绘页面元素。用户被困在查看空白白页。

的HTML规范明确指出,样式表是被包括在网页的HEAD:“与A,[LINK]可以仅出现在一个文档的HEAD部分,尽管它可能出现任意次数”。空白的黑屏或未样式化的内容闪烁均不值得冒险。最佳解决方案是遵循HTML规范并将样式表加载到文档HEAD中。

将脚本放在最下面

脚本引起的问题是它们阻止并行下载。的HTTP / 1.1规范建议的浏览器下载不超过每主机名并行两种组分。如果您从多个主机名提供图像,则可以并行进行两次以上的下载。但是,在下载脚本时,即使使用不同的主机名,浏览器也不会启动任何其他下载。

在某些情况下,将脚本移到底部并不容易。例如,如果脚本用于document.write插入页面内容的一部分,则不能将其在页面中移至较低位置。可能还会存在范围界定问题。在许多情况下,有一些方法可以解决这些情况。

经常出现的另一种建议是使用延迟脚本。该DEFER属性指示脚本不包含document.write,并且是浏览器可以继续呈现的线索。不幸的是,Firefox不支持该DEFER属性。在Internet Explorer中,该脚本可能会被延迟,但不会达到所需的程度。如果可以推迟脚本,则也可以将其移至页面底部。这将使您的网页加载更快。

避免CSS表达式

CSS表达式是一种动态设置CSS属性的强大(危险)方式。从版本5开始,Internet Explorer支持它们,但从IE8开始不推荐使用。例如,可以使用CSS表达式将背景色设置为每小时交替显示:

  背景颜色:expression((new Date())。getHours()%2?“#B8D4FF”:“#F08A00”);

如此处所示,该expression方法接受JavaScript表达式。CSS属性设置为评估JavaScript表达式的结果。该expression方法被其他浏览器忽略,因此对于在Internet Explorer中设置创建跨浏览器的一致体验所需的属性很有用。

表达式的问题在于对它们的评估比大多数人期望的要频繁。不仅会在呈现页面和调整页面大小时对它们进行评估,还会在滚动页面甚至用户将鼠标移到页面上时进行评估。在CSS表达式中添加一个计数器,使我们能够跟踪何时以及何时评估CSS表达式。在页面上移动鼠标可以轻松生成10,000多个评估。

减少对CSS表达式求值的次数的一种方法是使用一次性表达式,其中第一次对表达式求值时,它将style属性设置为显式值,该值替换CSS表达式。如果必须在页面的整个生命周期中动态设置样式属性,则可以使用事件处理程序代替CSS表达式。如果必须使用CSS表达式,请记住,它们可能会被评估数千次,并且可能会影响页面的性能。

将JavaScript和CSS设为外部

这些性能规则中有许多涉及如何管理外部组件。但是,在考虑这些因素之前,您应该提出一个更基本的问题:JavaScript和CSS是否应包含在外部文件中,还是应包含在页面本身中?

在现实世界中使用外部文件通常会产生更快的页面,因为JavaScript和CSS文件是由浏览器缓存的。每次请求HTML文档时,都会下载HTML文档中内联的JavaScript和CSS。这减少了所需的HTTP请求数量,但增加了HTML文档的大小。另一方面,如果JavaScript和CSS位于浏览器缓存的外部文件中,则可以在不增加HTTP请求数的情况下减小HTML文档的大小。

因此,关键因素是相对于请求的HTML文档数量而言,缓存外部JavaScript和CSS组件的频率。尽管难以量化,但可以使用各种度量标准来衡量此因素。如果您站点上的用户每个会话具有多个页面视图,并且您的许多页面都重复使用相同的脚本和样式表,则缓存的外部文件会带来更大的潜在利益。

许多网站都属于这些指标的中间。对于这些站点,最好的解决方案通常是将JavaScript和CSS部署为外部文件。最好使用内联的唯一例外是主页,例如Yahoo!的首页和My Yahoo!。。每个会话的页面浏览量很少(也许只有一个)的主页可能会发现,内联JavaScript和CSS可以缩短最终用户的响应时间。

对于通常是许多页面视图中第一个的首页,有些技术可以利用内联提供的HTTP请求的减少以及通过使用外部文件获得的缓存优势。一种这样的技术是在首页内联JavaScript和CSS,但是在页面加载完成后动态下载外部文件。后续页面将引用应该已经在浏览器缓存中的外部文件。

减少DNS查找

域名系统(DNS)会将主机名映射到IP地址,就像电话簿将人们的姓名映射到他们的电话号码一样。在浏览器中输入www.yahoo.com时,浏览器联系的DNS解析器将返回该服务器的IP地址。DNS有成本。DNS通常需要20-120毫秒来查找给定主机名的IP地址。在DNS查找完成之前,浏览器无法从该主机名下载任何内容。

缓存DNS查找以提高性能。此缓存可以在由用户的ISP或局域网维护的特殊缓存服务器上进行,但是在单个用户的计算机上也存在缓存。DNS信息保留在操作系统的DNS缓存中(Microsoft Windows上的“ DNS客户端服务”)。大多数浏览器都有自己的缓存,与操作系统的缓存分开。只要浏览器将DNS记录保留在其自己的缓存中,它就不会为请求记录而打扰操作系统。

默认情况下,Internet Explorer会缓存30分钟的DNS查找,这是由DnsCacheTimeout注册表设置指定的 。Firefox在network.dnsCacheExpiration配置设置的控制下缓存DNS查找1分钟。(Fasterfox将其更改为1小时。)

当客户端的DNS缓存为空时(对于浏览器和操作系统),DNS查找的数量等于网页中唯一主机名的数量。这包括在页面的URL,图像,脚本文件,样式表,Flash对象等中使用的主机名。减少唯一主机名的数量将减少DNS查找的数量。

减少唯一主机名的数量有可能减少页面中并行下载的数量。避免DNS查找会减少响应时间,但是减少并行下载可能会增加响应时间。我的指导原则是将这些组件划分为至少两个但不超过四个主机名。这导致在减少DNS查找与允许高度并行下载之间达成良好的折衷。

缩小JavaScript和CSS

最小化是从代码中删除不必要的字符以减小其大小,从而缩短加载时间的实践。当代码最小化时,所有注释以及不需要的空格字符(空格,换行符和制表符)都将被删除。在使用JavaScript的情况下,由于减小了下载文件的大小,因此可以提高响应时间性能。最小化JavaScript代码的两种流行工具是JSMin和YUI Compressor。YUI压缩器还可以缩小CSS。

混淆是可以应用于源代码的替代优化。它比缩小更复杂,因此由于混淆步骤本身而更容易产生错误。在对美国十大顶级网站的调查中,缩小后的大小减少了21%,而混淆处理的大小减少了25%。尽管混淆处理具有更大的减小大小的功能,但缩小JavaScript的风险较小。

除了最小化外部脚本和样式,内联script和style块也可以并且也应该被最小化。即使您对脚本和样式进行gzip压缩,将它们缩小也会使大小减小5%或更多。随着JavaScript和CSS的使用和大小的增加,通过减少代码量而节省的费用也将随之增加。

避免重定向

重定向使用301和302状态代码完成。这是301响应中HTTP标头的示例:

  HTTP / 1.1 301永久移动
  位置:http://example.com/newuri
  内容类型:text / html

浏览器会自动将用户带到该Location字段中指定的URL 。重定向所需的所有信息都在标头中。响应的正文通常为空。尽管有它们的名称,但实际上不会缓存301和302响应,除非有其他标头(例如Expires或Cache-Control)指示应该这样做。元刷新标记和JavaScript是将用户定向到其他URL的其他方法,但是,如果必须进行重定向,则首选技术是使用标准的3xx HTTP状态代码,主要是为了确保后退按钮可以正常工作。

要记住的主要事情是重定向会减慢用户体验。在用户和HTML文档之间插入重定向会延迟页面中的所有内容,因为无法呈现页面中的任何内容,并且只有在HTML文档到达之前,才能开始下载任何组件。

最浪费的重定向之一经常发生,并且Web开发人员通常不了解它。当URL末尾应包含一个斜杠(/)时,就会发生此错误。例如,转到http://astrology.yahoo.com/astrology会导致301响应,其中包含对http://astrology.yahoo.com/astrology/的重定向(请注意添加了斜杠)。如果使用Apache处理程序,则可以使用Alias或mod_rewrite或该DirectorySlash指令在Apache中进行修复。

将旧网站连接到新网站是重定向的另一种常见用法。其他包括连接网站的不同部分并根据某些条件(浏览器类型,用户帐户类型等)指导用户。使用重定向连接两个网站很简单,几乎不需要其他编码。尽管在这些情况下使用重定向会降低开发人员的复杂性,但会降低用户体验。这种使用重定向的替代方法包括使用Alias和mod_rewrite如果两个代码路径都托管在同一服务器上。如果域名更改是使用重定向的原因,则另一种方法是结合使用Alias或来创建CNAME(DNS记录,该记录创建从一个域名指向另一个域名的别名)mod_rewrite

删除重复的脚本

在同一页面中两次包含相同的JavaScript文件会损害性能。这并不像您想的那样异常。对美国十大顶级网站的审查显示,其中两个包含重复的脚本。两个主要因素增加了在单个网页中复制脚本的几率:团队规模和脚本数量。当确实发生这种情况时,重复的脚本会通过创建不必要的HTTP请求和浪费的JavaScript执行而损害性能。

不必要的HTTP请求在Internet Explorer中发生,但在Firefox中不发生。在Internet Explorer中,如果两次包含一个外部脚本且该脚本不可缓存,则它将在页面加载期间生成两个HTTP请求。即使脚本是可缓存的,当用户重新加载页面时,也会发生额外的HTTP请求。

除了生成浪费的HTTP请求之外,还浪费了多次评估脚本的时间。无论脚本是否可缓存,这种冗余的JavaScript执行都会在Firefox和Internet Explorer中进行。

避免两次意外包含相同脚本的一种方法是在模板系统中实现脚本管理模块。包含脚本的典型方法是在HTML页面中使用SCRIPT标记。

  <script type =“ text / javascript” src =“ menu_1.0.17.js”> </ script>

PHP中的一种替代方法是创建一个名为的函数insertScript。

  <?php insertScript(“ menu.js”)?>

除了防止多次插入同一脚本外,此功能还可以处理脚本的其他问题,例如依赖性检查以及向脚本文件名添加版本号以支持将来的Expires标头。

配置ETag

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

  HTTP / 1.1 200 OK
  上次修改时间:2006年12月12日,星期二,格林尼治标准时间
  ETag:“ 10c24bc-4ab-457e1c1f”
  内容长度:12195

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

  GET /i/yahoo.gif HTTP / 1.1
  主持人:us.yimg.com
  如果修改时间:自星期二,2006年12月12日格林尼治标准时间
  如果不匹配:“ 10c24bc-4ab-457e1c1f”
  HTTP / 1.1 304未修改

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

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

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

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

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

  FileETag无

使Ajax可缓存

Ajax引用的好处之一是,它向用户提供了即时反馈,因为它从后端Web服务器异步请求信息。但是,使用Ajax并不能保证用户不会在等待那些异步JavaScript和XML响应返回时挥手致意。在许多应用程序中,用户是否一直等待取决于Ajax的使用方式。例如,在基于Web的电子邮件客户端中,用户将一直等待Ajax请求的结果以查找与其搜索条件匹配的所有电子邮件。重要的是要记住,“异步”并不意味着“瞬时”。

为了提高性能,优化这些Ajax响应很重要。改善Ajax性能的最重要方法是使响应可缓存,如Add Expires或Cache-Control Header中所述。其他一些规则也适用于Ajax:
Gzip组件
减少DNS查找
缩小JavaScript
避免重定向
配置ETag

让我们来看一个例子。Web 2.0电子邮件客户端可能使用Ajax下载用户的地址簿以自动完成。如果用户自上次使用电子邮件Web应用以来没有修改过她的地址簿,那么如果该Ajax响应可以通过将来的Expires或Cache-Control标头进行缓存,则可以从缓存中读取先前的地址簿响应。必须告知浏览器何时使用先前缓存的通讯簿响应而不是请求新响应。可以通过向时间戳记Ajax URL添加时间戳,以指示用户最后一次修改其地址簿的时间,例如,&t=1190241612。如果自上次下载以来未修改过地址簿,则时间戳将相同,并且将从浏览器的缓存中读取地址簿,从而避免了额外的HTTP往返。如果用户修改了自己的通讯簿,则时间戳会确保新的URL与缓存的响应不匹配,浏览器将请求更新的通讯录条目。

即使您的Ajax响应是动态创建的,并且可能仅适用于单个用户,它们仍然可以被缓存。这样做将使您的Web 2.0应用程序更快。

尽早冲洗缓冲液

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

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

例:

  ... <!-CSS,JS->
</ head>
<?php flush(); ?>
<身体>
  ... <!-内容->

雅虎!搜索率先进行研究并进行实际用户测试,以证明使用此技术的好处。

使用GET处理AJAX请求

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

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

加载后组件

您可以仔细查看您的页面,然后问自己:“最初呈现页面绝对需要什么?”。其余的内容和组件可以等待。

JavaScript是onload事件之前和之后进行拆分的理想选择。例如,如果您有执行拖放操作的JavaScript代码和库以及动画,则它们可以等待,因为页面上的拖动元素是在初始渲染之后进行的。寻找后加载候选的其他地方包括隐藏内容(用户操作后出现的内容)和首屏以下的图像。

可以帮助您完成工作的工具:YUI Image Loader允许您将图像延迟到首屏以下,并且YUI Get实用程序是一种动态添加JS和CSS的简便方法。举个例子,看看Yahoo! Firebug的“ Net Panel”已打开的主页。

性能目标与其他Web开发最佳实践保持一致是很好的。在这种情况下,渐进增强的想法告诉我们,JavaScript受支持时可以改善用户体验,但是即使没有JavaScript,您也必须确保页面能够正常工作。因此,在确保页面正常运行之后,可以使用一些后期加载的脚本来增强页面的性能,这些脚本可以为您提供更多的便利,例如拖放和动画。

预载组件

预加载可能看起来与后加载相反,但实际上有一个不同的目标。通过预加载组件,您可以利用浏览器空闲的时间来请求将来需要的组件(例如图像,样式和脚本)。这样,当用户访问下一页时,您可能已经在缓存中包含了大多数组件,因此页面的加载将为用户带来更快的速度。

实际上有几种预加载类型:

无条件预加载-一旦onload触发,您就继续获取一些额外的组件。在google.com上查看有关如何在加载时请求子画面图片的示例。不需要在google.com主页上使用此图片图片,但在连续的搜索结果页面上则需要使用此图片图片。
有条件的预加载-根据用户操作,您可以进行有根据的猜测,预测用户下一步将到达何处,并进行相应的预加载。在search.yahoo.com上,您可以看到在开始在输入框中输入内容后如何请求一些额外的组件。
预期的预加载-启动重新设计之前的预加载。经过重新设计后,您通常会听到这样的消息:“新站点很酷,但是比以前慢。” 问题的一部分可能是用户访问了具有完整缓存的旧站点,但是新站点始终是空的缓存体验。您可以在启动重新设计之前预先加载一些组件来减轻这种副作用。您的旧站点可以使用浏览器空闲时的时间,并请求新站点将使用的图像和脚本

减少DOM元素的数量

复杂的页面意味着需要下载更多的字节,也意味着JavaScript中的DOM访问速度较慢。例如,当您想添加事件处理程序时,如果在页面上循环访问500或5000个DOM元素,则会有所不同。

大量的DOM元素可能是一种征兆,即页面的标记有一些需要改进的地方,而不必删除内容。您是否使用嵌套表进行布局?您是否

只为了解决布局问题而投入更多资源?也许有一种更好,更语义正确的方式来进行标记。

与布局有很大的帮助是YUI CSS公用事业:grids.css可以帮助你的整体布局,fonts.css和reset.css可以帮你除掉那些浏览器的默认格式。这是一个重新开始并思考您的标记的机会,例如,

仅在语义上有意义时才使用s,而不是因为它呈现了新的一行。

DOM元素的数量易于测试,只需在Firebug的控制台中输入:
document.getElementsByTagName(’*’).length

多少个DOM元素太多?检查其他具有良好标记的相似页面。例如Yahoo! 主页是一个非常繁忙的页面,仍然少于700个元素(HTML标记)。

跨域拆分组件

拆分组件使您可以最大程度地并行下载。确保您使用的域名不超过2-4个,因为DNS查询会受到影响。例如,您可以承载你的HTML和动态内容上www.example.org 与分裂之间的静电元件static1.example.org和static2.example.org

有关更多信息,请查看Tenni Theurer和Patty Chi撰写的“ 最大程度地在拼车通道中并行下载 ”。

减少iframe的数量

iframe可将HTML文档插入父文档中。了解iframe的工作方式非常重要,这样才能有效地使用它们。

<iframe> 优点:

帮助处理缓慢的第三方内容,例如徽章和广告
安全沙箱
并行下载脚本
<iframe> 缺点:

即使空白也很昂贵
阻止页面加载
非语义

没有404

HTTP请求非常昂贵,因此完全不需要发出HTTP请求并获得无用的响应(即404 Not Found),这会减慢用户体验,而没有任何好处。

一些站点具有有用的404“您是不是X吗?”,这对用户体验很有用,但也浪费了服务器资源(如数据库等)。特别糟糕的是,当指向外部JavaScript的链接错误并且结果为404时。首先,此下载将阻止并行下载。接下来,浏览器可能会尝试将404响应主体解析为JavaScript代码,试图在其中找到可用的内容。

减少Cookie大小

使用HTTP cookie的原因有多种,例如身份验证和个性化。有关cookie的信息在Web服务器和浏览器之间的HTTP标头中交换。保持Cookie的大小尽可能小很重要,以最大程度地减少对用户响应时间的影响。

有关更多信息,请查看 Tenni Theurer和Patty Chi撰写的“当Cookie崩溃时”。这项研究的主要内容:

消除不必要的Cookie
保持尽可能小的Cookie大小,以最大程度地减少对用户响应时间的影响
请注意在适当的域级别上设置Cookie,以免影响其他子域
适当设置到期日期。较早的失效日期或没有失效日期会更快地删除Cookie,从而缩短了用户响应时间

对组件使用无Cookie域

当浏览器发出静态图像请求并与请求一起发送cookie时,服务器对这些cookie没有任何用处。因此,它们只会无缘无故地创建网络流量。您应确保使用无Cookie的请求来请求静态组件。创建一个子域并在其中托管所有静态组件。

如果您的域是www.example.org,则可以在上托管静态组件static.example.org。但是,如果您已经在顶级域example.org(而不是)上设置了cookie www.example.org,则所有的请求都 static.example.org将包含这些cookie。在这种情况下,您可以购买一个全新的域,在其中托管静态组件,并使该域保持无Cookie状态。雅虎!使用yimg.com,YouTube使用ytimg.com,Amazon使用images-amazon.com等等。

在无cookie的域上托管静态组件的另一个好处是,某些代理可能拒绝缓存cookie所请求的组件。在相关说明中,如果您想在首页上使用example.org还是www.example.org,请考虑Cookie的影响。省略www会让您别无选择,只能将cookie写入*.example.org,因此出于性能原因,最好使用www子域并将cookie写入该子域。

最小化DOM访问

使用JavaScript访问DOM元素的速度很慢,因此为了使页面更具响应性,您应该:

缓存对已访问元素的引用
更新节点“离线”,然后将其添加到树中
避免使用JavaScript修复布局
有关更多信息,请查看 Julien Lecomte 的YUI剧院的 “高性能Ajax应用程序”。

开发智能事件处理程序

有时,页面会因为响应事件处理程序的响应性降低而出现问题,这是因为附加到DOM树的不同元素上的事件处理程序过多,因而导致执行频率太高。这就是为什么使用事件委托是一种好方法。如果a中有10个按钮div,则仅将一个事件处理程序附加到div包装器,而不是每个按钮一个处理程序。事件冒泡了,因此您可以捕获事件并弄清楚它来自哪个按钮。

您也无需等待onload事件即可开始对DOM树进行操作。通常,您需要的只是您要访问的元素在树中可用。您不必等待所有图像都下载。 DOMContentLoaded是您可能考虑使用的事件,而不是onload,但是在所有浏览器中都可用之前,您可以使用具有方法的YUI Event实用程序onAvailable。

有关更多信息,请查看 Julien Lecomte 的YUI剧院的 “高性能Ajax应用程序”。

在@import上选择

以前的最佳实践之一指出,CSS应该位于顶部,以便进行渐进式渲染。

在IE中,@import其行为与页面底部的使用相同,因此最好不要使用它。

避免使用过滤器

IE专有AlphaImageLoader过滤器旨在解决IE版本<7中的半透明真彩色PNG问题。此过滤器的问题在于,它会阻止渲染并在下载图像时冻结浏览器。它还增加了内存消耗,并且按元素而不是按图像应用,因此问题倍增。

最好的方法是AlphaImageLoader完全避免使用PNG8并降低其性能,这在IE中很好。如果绝对需要AlphaImageLoader,请使用下划线_filter,以免对IE7 +用户造成不利影响。

优化图像

设计人员完成了为您的网页创建图像后,仍然可以尝试一些操作,然后再将这些图像通过FTP传输到Web服务器。

您可以检查GIF,并查看它们是否使用的调色板尺寸与图像中的颜色数量相对应。使用imagemagick可以很容易地进行检查。
identify -verbose image.gif
当您在调色板中看到使用4种颜色和256种颜色“插槽”的图像时,还有改进的余地。
尝试将GIF转换为PNG,看看是否有节省。经常有。由于浏览器支持有限,开发人员常常不愿使用PNG,但这已成为过去。唯一的实际问题是真彩色PNG中的alpha透明性,但是同样,GIF也不是真彩色,也不支持可变透明度。因此,GIF可以做的任何事情,调色板PNG(PNG8)也可以做(动画除外)。这个简单的imagemagick命令产生了完全安全使用的PNG:
convert image.gif image.png
“我们要说的是:给PiNG一个机会!”
在所有PNG上 运行pngcrush(或任何其他PNG优化器工具)。例:
pngcrush image.png -rem alla -reduce -brute result.png
在所有JPEG上运行jpegtran。此工具执行无损JPEG操作(例如旋转),还可以用于优化和删除图像中的注释和其他无用信息(例如EXIF信息)。
jpegtran -copy none -optimize -perfect src.jpg dest.jpg

优化CSS精灵

将图片中的图片水平排列而不是垂直排列通常会减小文件大小。
在子画面中组合相似的颜色可以帮助您保持较低的颜色计数,理想情况下应少于256种颜色,以适合PNG8。
“对移动设备友好”,并且在sprite中的图像之间不要留有很大的空隙。这不会对文件大小产生太大影响,但需要较少的内存供用户代理将图像解压缩为像素图。100x100图片为1万像素,其中1000x1000为100万像素

不要缩放HTML中的图像

不要使用比您需要的大的图像,仅因为可以在HTML中设置宽度和高度。如果需要,

<img width="100" height="100" src="mycat.jpg" alt="My Cat" />

则图像(mycat.jpg)应该为100x100px,而不是缩小为500x500px的图像。

使favicon.ico小型且可缓存

favicon.ico是保留在服务器根目录中的映像。这是一个必不可少的邪恶,因为即使您不关心它,浏览器仍然会请求它,因此最好不要使用来响应404 Not Found。另外,由于它在同一台服务器上,因此每次请求时都会发送cookie。该映像还会干扰下载顺序,例如,在IE中,当您在onload中请求其他组件时,将在这些其他组件之前下载图标。

因此,要减轻拥有favicon.ico的弊端,请确保:

它很小,最好在1K以下。
根据需要设置Expires标头(因为如果决定更改它,则无法重命名)。您可能可以在未来几个月安全地设置Expires标头。您可以检查当前favicon.ico的最后修改日期,以做出明智的决定。
Imagemagick可以帮助您创建小型网站图标

组件保持在25K以下

此限制与以下事实有关:iPhone不会缓存大于25K的组件。请注意,这是未压缩的大小。在这里,缩小非常重要,因为仅使用gzip可能不够。

有关更多信息,请查看Wayne Shea和Tenni Theurer撰写的“ 性能研究,第5部分:iPhone缓存能力-坚持下去 ”。
将组件打包成多部分文档
日:移动

将组件打包到一个多部分文档中就像一封带有附件的电子邮件,它可以帮助您通过一个HTTP请求获取多个组件(请记住:HTTP请求很昂贵)。使用此技术时,请首先检查用户代理是否支持它(iPhone不支持)。

避免空图片源

具有空字符串src属性的图像出现的次数超过预期。它以两种形式出现:

直接HTML

<img src =“”>

的JavaScript

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

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

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

为什么这种行为不好?

通过发送大量意外流量来破坏服务器,尤其是对于每天获得数百万次页面查看的页面。
浪费的服务器计算周期生成了永远不会被查看的页面。
可能损坏用户数据。如果您正在通过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属性的值不能为空字符串。
希望将来浏览器不会出现此问题。不幸的是,对于<script src =“”>和<link href =“”>没有此类子句。也许还有时间进行调整,以确保浏览器不会意外实现此行为。

发布了1 篇原创文章 · 获赞 1 · 访问量 17

猜你喜欢

转载自blog.csdn.net/Azery/article/details/104458675
今日推荐