翻译自:http://www.netmagazine.com/tutorials/make-your-sites-load-faster

 

   速度对每个网站都至关重要。众所周知Google将网站速度作为搜索结果的一个衡量标准。这说明访问者更喜欢速度快的网站,这毫无争议!

   Jakob Nielsen在1993年写过一篇文章 the three limits of response times 。虽然这个研究从因特网的标准来看有点旧,但是我们的心理在这19年时间里并没有太大变化。Jakob声称响应时间在0.1秒内的系统被认为是瞬时的。网页加载时间在0.1秒以内似乎不可能;Google UK的最佳加载时间是0.34秒,是一个更合理的基准。页面加载时间在0.34到1秒都是可以实现和有意义的。

 

慢的代价

   这些目标对你的网站和商务有现实意义。在Google工作的Marissa Mayer在2006年发表过一个实验,实验中提到搜索引擎返回的结果增加到了30个,使得页面加载时间增加了大概500ms,并导致20%的流量减少。Amazon人为地让页面加载时间增加100ms延迟并发现“即使是非常小的延迟也会导致细微的收入减少”。

  

     开源的Web网页性能评级插件YSlow基于Yahoo Developer Network的网站性能推荐,链接:http://developer.yahoo.com/performance/rules.html/

   其他因网站速度慢而导致的不利联想包括:低可信度、低认可度和缺乏吸引力。我们在浏览一些网站时也许都体会过受挫感和血压升高。那么我们该如何做来使得我们的网站足够快从而避免上面的这些问题呢?

   第一件需要考虑的是HTML代码的体积。这是最容易被忽视的领域之一,也许是因为人们认为它与网络带宽的关联并没那么紧密。一些内容管理系统在他们输出的内容体积上非常随意。作为一般性的指导原则,你应该让大部分页面的HTML代码体积小于50KB,如果小于20KB那就更完美了。显然有一些例外情况,但这应该作为经验法则。

   记住这点也很重要:人们现在比以前更多地使用移动设备浏览网站。不同移动设备浏览同一个网站的速度差异是非常显著的,主要因为它们的传输速率低于有线传输连接的传输速率。如果两个竞争者网站的每个页面都相差100KB,那么这意味着在一些较慢的移动网络中1秒钟的加载时间差异,正好落入Jakob Nielsen的“interrupted thought flow”区间内。快速网站让用户的受挫感大大减少,并且在与同类但臃肿的竞争网站的较量中脱颖而出,也能吸引更多的用户回访。

  

   有一些高质量的衡量性能的资源,比如Google的PageSpeed

   大部分Web服务器的一大重要特性就是能够压缩HTML。由于HTML包含很多重复数据,使得HTML成为数据压缩的首选。例如,一个主页的HTML体积为18.1KB通过压缩减少到6.3KB。节省了65%。文本体积越大压缩算法效率越高,所以对体积比较大的HTML进行压缩能得到显著的节省。某个流行论坛的页面使用压缩后,HTML体积由138.1K减少到25.7K,节省超过80%,将大大减少资源传输时间。这种压缩HTML的方式几乎没有任何副作用;每个人都应该对他的HTML内容应用这种方式。一些Web服务器对于静态内容压缩和动态生成内容的压缩有不同的设置,所以可能的话确保你为两种格式的内容都应用HTML压缩。

   

  IIS7 Web服务器截图,展示了要支持静态内容和动态内容是多么的简单

 

CDN

   内容分发网络(content delivery networks,CDN)也可以显著减少网站的加载时间。CDNs是一组分布全球的服务器,每个服务器都保存了一份内容的拷贝。当用户从你的网站请求一张图片,假这张图片也保存在CDN上,离用户最近的CDN服务器将返回图片给用户。

   有许多可用的CDN服务。一些CDN服务非常贵,但它们声称将提供比便宜CDN更好的性能。免费CDN服务也在兴起,它们是否真能改善我们的网站性能值得验证。

   使用CDN时的一个重要考虑是确保你正确建立了CDN,而不会因此丢失SEO值。你或许会从你的域名接收到大量的来自图像的流量,通过将图片移到外部域可能会对你的网站流量不利。Amazon S3服务使得你可以将一个子域指向它的CDN,这是一个非常不错的CDN特性。

 

   Pingdom的免费工具可以帮助分析网页的”瀑布流“和分析每个资源的加载时间,有助于找出性能瓶颈

   将内容分发在不同的域(比如CDN)或者子域(这些域都没有cookie),也有另外一个比较大的优势。当在一个域名上设置cookie后,浏览器对该域名下的每个资源的每个请求都会携带cookie数据。但通常对于静态内容如图片、CSS或者JS文件并不需要cookie。Web用户的上传速率通常远慢于下载速率,这也可能导致页面加载速度的大幅减慢。通过将静态内容存在一个不同的域下,浏览器将不会发送不必要的cookie数据(因为同源策略)。这将大大加快资源的请求时间。

   Cookie占了HTTP请求的相当比重。1,500字节是最常用的单个数据包尺寸限制,所以如果你要保证HTTP请求在这个限制内那么整个HTTP请求能够通过一个数据包发送完。Google建议cookies大小不应超过400字节 - 这对于保证网站的HTTP请求满足”1数据包/1500字节“限制,很有意义。

 

更多技巧

   还有其他一些容易实现但能带来巨大收益的技巧。其中之一是将JavaScript脚本放在HTML文档底部,即</body>之前,因为浏览器对于同一个主机能够进行的并行下载数有限制。最初HTTP 1.1规范建议浏览器从每个主机并行下载的资源数不超过2。但现代浏览器一般将这个值设为6。如果你的网页包含的资源数(如图片、JavaScript、CSS文件)超过6,那么将这些资源分布到不同的域(比如子域或者CDN)下可能带来性能提升。

  

   Sprite技术很容易实现,也能带来显著的性能提升,因为它减少了HTTP请求次数

   与其将不同的请求分派到不同的域,你或许可以考虑整合这些请求。每个HTTP请求都是有开销的。如果你的网站上的几十个图片都作为单独的资源,将产生严重的浪费并导致网站速度减慢。通过将这些图片整合到一张图片,即Sprite技术,你可以减少请求数。主要通过CSS的background-position属性来实现CSS Sprite技术。

   Sprite还有其他优势。如果你使用了鼠标悬停图片,将这些图片存在同一个Sprite Sheet中意味着一旦mouseover事件初始化后将没有延迟,因为鼠标悬停图片已经完全下载到了本地。这将大大减少用户感知加载时间。

   在<img/>标签中指定所有图片的宽高也是减少网页感知加载时间的一个重要因素。很多开发者不为图片显式设置宽高。这就爱个呢导致页面的尺寸跳跃式增加,给用户带来”滞顿“的感觉。相反如果显式设定图片的尺寸,浏览器在加载图片时将预留空间,从而阻止页面尺寸突然变化,带来更好的的用户体验。

   我们还可以做什么来改善呢?预先获取(Prefetching)是HTML5中的一个新特性。预先获取使得可以在用户实际请求资源前加载页面资源。当前只有火狐和Chrome浏览器支持。但是它的容易实现和在改善认知加载时间的用处上具有很大意义,值得考虑实现:

<!&mdash;Firefox Prefetching –>
<link rel="prefetch" href="http://www.example.com/page2.html">
<!&mdash;Chrome Prerender –>
<link rel="prerender" href="http://www.example.com/page2.html">
<!&mdash;Both in one line –>
<link rel="prefetch prerender" href="http://www.example.com/page2.html">

   prefetching和prerendering有一个行为上的差异。Mozilla的prefetch将只加载给定URL对应的顶级资源,一般是HTML页面本身。而Google的prerender还会加载子资源,用Google自己的话说”does all of the work necessary to show the page to the user, without actually showing it until the user clicks”。

  

   Google Analytics包含几个有用的工具可以帮助诊断最慢的网页

 

使用prefetching和prerendering时需要考虑的

   使用这两个特性时也需要格外注意。如果prerender/prefetch的资源太多的话,用户的整体浏览体验将会受损。如果你还有服务端的统计,也将受影响。如果用户并没有点击预加载的资源就离开网站了,你的统计器可能将这次访问算作2次PV,而不是实际的1次PV。这对于一些重要的指标如跳出率来说会产生误导。Chrome的prerender还有另外一个值得开发者注意的地方:被prerender的页面将会执行javaScript。prerender加载页面的方式基本与用户点击链接一样。这对于第三方的脚本比如广告脚本和统计追踪脚本至关重要。不恰当地处理这些资源将会再次使得你对重要指标的统计结果曲线非常倾斜。

   对分页内容是用prefetch和prerender可能比较保险和有用。例如一个教程网站的网页被分成不同的区块。尤其应该注意让教程内容区块满足Nielsen的“uninterrupted thought flow”时间限制。Google Analytics也能提供有用的信息来指导你该为哪个页面应用prerender/prefetch。使用它的内置Analytics你可以决定首页的哪个链接最常被点击。一些情况下,某个链接被点击次数占总点击次数的很大比重,这种情况下很适合使用预加载技术。

   prefetching和prerendering都能跨域工作-浏览器在这点上意外地放宽了限制,因为浏览器对于跨域一般限制非常严格。

   prefetching尤其是prerendering对于感知加载时间的减少意义重大。但是了解它们是如何工作的并保证用户的浏览体验不会被直接或者间接影响至关重要。

 

Ajax内容加载

   另外一个减少加载时间的方式是使用Ajax加载内容而不是完整地从头加载页面。这更有效率因为它只加载变化的内容,而不加载变化的内容外的部分。

   但是过度使用Ajax将破话浏览体验。如果使用不合理的话,浏览器的后退和前进按钮可能不会像用户预期那样工作,并且类似给页面加书签或者刷新页面的行为可能也会以出乎意料的方式工作。当设计网站时,建议不要干涉这些底层行为。这将使得用户很困惑,也显得非常不友好。有一个基本的例子是一些网站为了阻止用户拷贝复制而屏蔽了鼠标右键。虽然使用Ajax产生的后果和屏蔽右键不一样,但是效果也是类似的。

   HTML5引入History API,在某种程度上解决了这些问题。它被多个浏览器支持(除了IE,虽然计划在IE 10中支持)。使用HTML5 History API我们可以通过Ajax加载内容,而同时又能模拟正常的浏览体验。当使用得当时,后退、前进和刷新按钮都将按预期工作。地址栏URL也将被更新,意味着书签功能现在也恢复正常了。如果合理地实现,你可以避免对很多资源进行重复加载,同时又能对禁用JavaScript的浏览器实现优雅的向后兼容(fall back)。

  

   Chrome Web Store通过Ajax结合这种方式加载很多内容,提供快速、自然的浏览体验

   但是仍然有一个很大的缺陷:取决于你要构建的网站的复杂度和功能,结合History API实现Ajax内容加载并对用户不可见是困难的。如果网站还是用了服务端脚本,你或许会发现你得为每个东西书写两次:一次JavaScript,一次服务端脚本。这将导致维护问题和不一致性。

   当尝试改善你的网站的性能时,你或许会遇到一些难以解决的问题。但正如本文开头提到的,Google使用页面加载速度作为重要的搜索结果排名标准,这点应该成为你改进网站速率的重要动机。但是你或许注意到当你使用Google Webmaster Tool这类工具时,它们报告的页面速度比你预期的更慢。其原因可能是第三方脚本比如Facebook或者Twitter的分享按钮。这些经常耗费数百毫秒的等待时间,拖慢整个站点的加载时间。但是这并不能作为移除这些脚本的理由-因为很可能保留这些社交媒体按钮对你的网站更重要。这些按钮通常占据网页很小的空间,所以对访客的感知加载时间不会有太大影响-这点是我们做性能调优时需要重点关注的。

posted on 2013-02-25 19:46  feichexia  阅读(310)  评论(0编辑  收藏  举报