优化网站性能的35条规则

2018-07-16 03:11:26来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

1. 最小化HTTP请求次数

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

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

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

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

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

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

减少页面中HTTP请求的数量是可以开始的地方。这是提高首次访问者性能的最重要指南。正如Tenni Theurer的博客文章浏览器缓存使用 - 暴露!,您网站的每日访问者中有40-60%使用空缓存。让这些首次访问者快速访问页面是获得更好用户体验的关键。

2. 使用内容分发网络(CDN)

       用户与Web服务器的距离会对响应时间产生影响。在多个地理位置分散的服务器上部署内容将使您的页面从用户的角度加载更快。但是你应该从哪里开始呢?

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

请记住,最终用户响应时间的80-90%用于下载页面中的所有组件:图像,样式表,脚本,Flash等。这是性能黄金规则而不是从重新设计应用程序架构的艰巨任务开始,最好先分散静态内容。这不仅可以缩短响应时间,而且由于内容交付网络,它更容易实现。

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

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

3. 添加Expires或Cache-Control标头

这条规则有两个方面:

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

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

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

Expires: Thu, 15 Apr 2010 20:00:00 GMT

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

ExpiresDefault "access plus 10 years"

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

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

       4. 使用Gzip组件

       通过前端工程师做出的决策,可以显着减少在网络上传输HTTP请求和响应所需的时间。确实,最终用户的带宽速度,互联网服务提供商,与对等交换点的距离等都超出了开发团队的控制范围。但是还有其他变量会影响响应时间。压缩通过减少HTTP响应的大小来减少响应时间。

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

Accept-Encoding:gzip,deflate

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

Content-Encoding:gzip

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

       Gzipping通常将响应大小减少约70%。今天大约90%的互联网流量通过声称支持gzip的浏览器传播。如果你使用Apache,配置gzip的模块取决于你的版本:Apache 1.3使用mod_gzip而Apache 2.x使用mod_deflate

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

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

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

       5. 将CSS样式表放在顶部

       在研究Yahoo!的性能时,我们发现将样式表移动到文档HEAD会使页面看起来加载速度更快。这是因为将样式表放在HEAD中允许页面逐步呈现。

       关注性能的前端工程师希望页面逐步加载; 也就是说,我们希望浏览器尽快显示它拥有的任何内容。这对于具有大量内容的页面和对较慢Internet连接的用户尤其重要。为用户提供视觉反馈(例如进度指示器)的重要性已得到很好的研究和记录在我们的例子中,HTML页面是进度指示器!当浏览器逐步加载页面时,标题,导航栏,顶部的徽标等都作为等待页面的用户的视觉反馈。这改善了整体用户体验。

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

       HTML规范明确指出,样式表是被包括在网页的HEAD:“与A,[LINK]可以仅出现在一个文档的HEAD部分,尽管它可能出现任意次数”。这些替代品,空白的白色屏幕或无风格内容的闪光都是值得冒险的。最佳解决方案是遵循HTML规范并在文档HEAD中加载样式表。

       6. 将JavaScript脚本放在底部

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

       在某些情况下,将脚本移到底部并不容易。例如,如果脚本用于document.write插入页面内容的一部分,则无法在页面中向下移动。可能还存在范围问题。在许多情况下,有办法解决这些问题。

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

       7. 避免使用CSS中的expressions

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

background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" );

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

       表达式的问题在于它们的评估频率高于大多数人的预期。它们不仅在页面呈现和调整大小时进行评估,而且在页面滚动时甚至在用户将鼠标移动到页面上时进行评估。在CSS表达式中添加计数器可以让我们跟踪CSS表达式的计算时间和频率。在页面上移动鼠标可以轻松生成10,000多个评估。

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

       8. 将JavaScript和CSS独立成外部文件

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

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

       因此,关键因素是外部JavaScript和CSS组件相对于请求的HTML文档数量的缓存频率。这个因素虽然难以量化,但可以使用各种指标进行衡量。如果您站点上的用户每个会话有多个页面查看,并且您的许多页面重复使用相同的脚本和样式表,则缓存的外部文件可能会带来更大的潜在好处。

       许多网站都处于这些指标的中间。对于这些站点,最佳解决方案通常是将JavaScript和CSS部署为外部文件。内联的唯一例外是主页,例如Yahoo!的首页My Yahoo! 每个会话具有很少(可能只有一个)页面视图的主页可能会发现内联JavaScript和CSS会导致更快的最终用户响应时间。

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

       9. 减少DNS查询

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

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

  默认情况下,Internet Explorer会将DNS查找缓存30分钟,具体 DnsCacheTimeout取决于注册表设置。Firefox将DNS查找缓存1分钟,由network.dnsCacheExpiration配置设置控制(Fasterfox将此更改为1小时。)

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

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

       10. 压缩JavaScript和CSS(包括内联<script>和<style>)

  压缩是从代码中删除不必要的字符以减小其大小从而改善加载时间的做法。压缩代码时,将删除所有注释,以及不需要的空格字符(空格,换行符和制表符)。在JavaScript的情况下,这改善了响应时间性能,因为下载文件的大小减小了。用于压缩JavaScript代码的两种流行工具是JSMin和YUI Compressor。YUI压缩器也可以压缩CSS。

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

  除了压缩外部脚本和样式之外,内联<script><style>块也可以并且也应该压缩。即使你gzip你的脚本和样式,压缩它们仍然会减小5%或更多的大小。随着JavaScript和CSS的使用和大小的增加,压缩代码所节省的成本也会增加。

       11. 避免重定向

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

HTTP/1.1 301 Moved Permanently
Location: http://example.com/newuri
Content-Type: text/html

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

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

  最浪费的重定向之一经常发生,Web开发人员通常不了解它。当URL中缺少尾部斜杠(/)时会发生这种情况。例如,转到http://astrology.yahoo.com/astrology会产生301响应,其中包含重定向到http://astrology.yahoo.com/astrology/(注意添加的尾部斜杠)。如果您使用的是Apache处理程序,则可以使用Aliasor mod_rewriteDirectorySlash指令在Apache中修复此问题

  将旧网站连接到新网站是重定向的另一种常见用途。其他包括连接网站的不同部分并基于特定条件(浏览器类型,用户帐户类型等)指导用户。使用重定向连接两个网站很简单,只需要很少的额外编码。虽然在这些情况下使用重定向会降低开发人员的复杂性,但会降低用户体验。使用重定向的替代方法包括使用Alias以及mod_rewrite两个代码路径是否托管在同一服务器上。如果域名更改是使用重定向的原因,则另一种方法是创建CNAME(创建从一个域名指向另一个域名的别名的DNS记录)与Alias组合mod_rewrite

       12. 删除重复的脚本

  在一个页面中两次包含相同的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头。

       13. 配置实体标记ETag

       14. 使Ajax可以缓存

       15. 尽早清除缓冲区

       16. 使用GET进行Ajax请求

       17. 延迟加载组件

       18. 预加载组件

       19. 减少DOM元素的数量

       20. 跨域拆分组件

       21. 最小化iframe数量

       22. 不出现404s

       23. 减小Cookie大小

       24. 对组建使用cookie-free的域名

       25. 最小化DOM的访问次数

       26. 开发巧妙的事件处理程序

       27. 优先选择使用<link>而非@import

       28. 避免使用filters

       29. 优化图片

       30.优化CSS Sprites

       31. 不要在HTML中缩放图像

       32. 减小favicon.ico的体积并缓存

       33. 保持组件小于25K

       34. 将组件拆分到多个文档中

       35. 避免设置空图像的src

参考:

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:小程序实践(六):view内部组件排版

下一篇:IE中操作粘贴板复制和粘贴