2757com 6

以及一些浏览器怎样工作的基础知识2757com:,主要从八个方向分别介绍了如何进行性能的优化

Web性能优化系列 – 通过提前获取DNS来提升网页加载速度

2015/04/23 · HTML5 ·
DNS,
性能优化

本文由 伯乐在线 –
刘健超-J.c
翻译,sunbiaobiao
校稿。未经许可,禁止转载!
英文出处:www.deanhume.com。欢迎加入翻译组。

我时常寻找方法改善网站性能,为的就是能提供更佳的用户体验。也许你经常会发现你的网站运行高效且性能优异。你也可能曾让你的应用程序在Google
PageSpeed或Yahoo!
YSlow进行测试,并得到高分。然而,有一样东西一直影响页面加载时间。它在一个页面上,花费很多时间去查找不同组件的DNS。例如,下面这幅图片展示了我的博客首页所需资源的加载瀑布图。

2757com 1

请注意条形图的灰蓝色部分,它出现在瀑布图中的大部分组件前。这灰蓝色代表下载资源前查找DNS所需时间。这竟然占了组件下载时间的很大部分!即使组件进行了优化,并已经最小化/合并/压缩处理,你仍然需要等待查找DNS时间。我利用webpagetest.org做了一个关于该网站DNS查找时间的表格。

2757com 2

从上图可看到,DNS查找时间都很高,
如果能减少该时间并提速,便会让资源加载变得更加高效。幸运的是,有个很棒的技巧能让网站的加载时间变得更快。它被称为DNS预取,并且很容易实现。你所需做的是,在网页顶部添加以下属性作为链接(link)。

<link rel="dns-prefetch" href="//host_name_to_prefetch.com">

DNS预取是在用户尝试点击链接前试图解析域名。一旦域名被解析,且用户导航到该域名,则不会因DNS查找而导致加载时间变长。在这个博客主页里,有很多跳转到不同帖子的链接。如果能在用户导航到下一个页面前,预取一些外部链接的DNS,这将会大大减少下一个页面的DNS查找时间。根据Chromium
documentation所说,如果用户能将域名解析成IP地址并且缓存之,则DNS查找时间能低至0-1毫秒(千分之一秒)。这是相当令人印象深刻的!

我在网站添加DNS预取功能后,确实能显著改善页面加载时间。目前,这项技术被大多数主流浏览器所支持(除了IE),所以,当前没有任何理由不在你的web应用上使用这项技术!DNS预取是一个安全的HTML5特性,它会被那些不支持该技术的老旧浏览器简单忽略掉。如果你的网页内容是来自多个域名,那么这绝对是一个聪明的,能加快页面加载速度的方法。

打赏支持我翻译更多好文章,谢谢!

打赏译者

本文大部分内容翻译自雅虎前端的性能优化,如何让页面加载更快,雅虎给出了多个规则,原文地址:Best
Practices for Speeding Up Your Web Site
。主要从八个方向分别介绍了如何进行性能的优化。

这是一篇关于 <u>如何加快网站访问速度</u> 的译文,原文出自
雅虎开发者网站,原标题为
Best Practices for Speeding Up Your Web
Site。

本文是大名鼎鼎的雅虎前端优化规则(Yslow)的翻译。翻译并不逐字逐句,部分难以逐字翻译的被意译了,另外一些不重要的举例等也被精简。

在这篇长文章中,我将分享个人项目经验,一些关于快速简单且非常有趣的WEB性能知识的点点滴滴,以便使你的行为可以像一个初级的网页设计师和前端开发者;希望对任何想开始学习性能的人,有一定的启迪作用,并使你的前端项目变得超快。我相信这些技巧你能很快掌握,并轻松实现。因为都只需要一点小技巧,以及一些浏览器怎样工作的基础知识。

打赏支持我翻译更多好文章,谢谢!

任选一种支付方式

2757com 3
2757com 4

赞 1 收藏
评论

1.1 最小化HTTP请求

雅虎军规上说明80%的响应时间都来自前端,大多数页面的加载时间都是在下载图片,样式,js,flash等,减少组件的数量反过来减少请求的数量是页面加载更快的关键。

减少页面组件数量的一种方法是简化页面设计,但是如何在构建更丰富内容的基础上,同时还能减少相应时间?

  • Combined file
    ,合并文件,可以通过合并JavaScript,CSS文件来减少HTTP请求的数量来缩短响应时间。
  • CSS Sprites
    ,CSS精灵,是减少图片请求数量的首选方法,通过将背景图合并为单个图像,
    通过background-imagebackground-position
    属性来显示部分需要的图像。
  • Image maps
    ,图像地图,通过将多张图片合成为一张图片,整体大小大致相同,但减少HTTP请求的数量会加快页面的速度。
    一般用于如导航条 ,定义图像坐标容易出错,不推荐使用。
  • Inline images
    ,内联图像,使用data:url scheme将图像嵌入实际页面中。

以下为译文:

本文从内容,服务器,图片,css,js,cookie,和组件7个部分来谈网站优化。

注意
本文需要预先知晓一些基础的性能知识,如果有任何你不熟悉的就Google搜索一下好了!

关于作者:刘健超-J.c

2757com 5

前端,在路上…
个人主页 ·
我的文章 ·
19 ·
    

2757com 6

1.2 减少DNS查找

DNS就像电话簿将人们的姓名映射到他们的电话号码一样,当您输入www.yahoo.com时,浏览器会通过DNS解析返回服务器的IP地址,这个DNS解析过程需要成本,通常需要20-120ms才能解析成功,在这之前,浏览器无法从服务器获取任何内容。

通过缓存DNS查找来获得更好的性能。DNS信息保留在操作系统的DNS缓存中,大多数的浏览器都有自己的缓存,与操作系统的分开。

默认情况,IE会将DNS查找缓存30分钟,FireFox缓存一分钟。

当客户端的DNS缓存为空(对于浏览器和操作系统)时,DNS查找的数量等于网页中唯一主机名的数量。
减少唯一主机名的数量可减少DNS查找的数量。

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


原文:Creeper
地址:https://github.com/creeperyang/blog/issues/1

基础知识

1.3 避免重定向

使用301和302状态码完成重定向。下面是一个301响应http头示例:

HTTP/1.1 301 Moved PermanentlyLocation: http://example.com/newuriContent-Type: text/html

浏览器自动将用户带到Location字段指定的URL。跳转所需的所有信息都在http头
,响应的主体通常是空的。301或302响应一般不会被缓存,除非有Expires
或者Cache-Control 指定要缓存。

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

最浪费的重定向之一经常发生,就是在URL中缺少尾部/
会产生301响应,比如http://astrology.yahoo.com/astrology301跳转到http://astrology.yahoo.com/astrology/

加速网站访问的最佳实践

卓越的绩效团队已经确定了一些使网页快速的最佳做法。该清单包括分为7个类别的35个最佳做法。


如何让web页面更快,雅虎团队实践总结了7类35条规则,下面一一列出。

关于性能,有一些知识在所有的设计师和前端开发者中广为传播。例如,尽可能少的请求,优化图片,把样式表(stylesheets)放在<head>,
把JS放在</body>之前, 最小化(minifying) JS 和 CSS
等等。这些基础知识已经被用来加快用户响应了,但还有更多更多需要学习。

1.4 使Ajax可缓存

使Ajax可缓存的好处之一就是在用户请求时可以提供快速反馈,因为它从后端Web服务器异步请求信息。重要的是要记住“异步”并不意味着“瞬时”。

为了提高性能,优化这些Ajax响应非常重要。提高Ajax性能的最重要方法是使响应可缓存,其中提高的方法除了Add
an Expires or a Cache-Control Header 中讨论的之外,其他方法还有:

  • gzip组件
  • 减少DNS查找
  • 压缩JS
  • 避免重定向
  • 设置ETags

Content

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

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

组合文件
是通过将所有脚本组合到单个脚本中以及将所有CSS组合到单个样式表中的方式来减少HTTP请求的数量。当脚本和样式表从页到页不同时,组合文件更具挑战性,但使这部分版本过程能够改善响应时间。

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

图像映像将多个图像组合成单个图像。总体大小大致相同,但减少HTTP请求数量会加快页面速度。如果图像在页面中是连续的,则图像映射只能工作,例如导航栏。定义图像映射的坐标可能很繁琐,容易出错。

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

减少页面中HTTP请求的数量是开始的地方。这是提高首次访问者效能的最重要的指导方针。如Tenni
Theurer的博客文章中所述浏览器缓存使用 –
暴露!,您网站的每日访问者中有40-60%的空白缓存。

使您的页面快速为这些第一次访问者是更好的用户体验的关键。

  1. 减少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查找并允许高度并行下载之间的良好折中。

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

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

浏览器自动将用户带到该Location字段中指定的URL。重定向所需的所有信息都在头文件中。响应的身体通常是空的。尽管他们的名字,在实践中也不会缓存301和302的响应,除非额外的标题,例如
Expires或者Cache-Control表明它应该是。元刷新标签和JavaScript是将用户引导到其他URL的其他方法,但如果必须执行重定向,首选技术是使用标准的3xx
HTTP状态代码,主要是为了确保后退按钮正常工作。

要记住的是重定向会减慢用户体验。在用户和HTML文档之间插入重定向会延迟页面中的所有内容,因为页面中的任何内容都不能被渲染,并且在HTML文档到达之前不会开始下载任何组件。

最浪费的重定向之一是频繁发生的,Web开发人员通常不会意识到这一点。当URL中缺少尾部斜线(/)时,会发生这种情况,否则应该有一个。
例如,去
http://astrology.yahoo.com/astrology
得到一个包含重定向到
http://astrology.yahoo.com/astrology/
(注意添加的尾部斜杠)的301响应。如果您使用Apache处理程序,则使用Aliasormod_rewriteor
DirectorySlash指令在Apache中进行修复。

将旧网站连接到新的网站是重定向的另一个常见用途。其他包括连接网站的不同部分,并根据某些条件(浏览器类型,用户帐户类型等)指导用户。使用重定向连接两个网站很简单,只需要很少的附加编码。尽管在这些情况下使用重定向会降低开发人员的复杂性,但会降低用户体验。这种使用重定向的替代方案包括使用Aliasmod_rewrite如果两个代码路径托管在同一台服务器上。如果域名变化是使用重定向的原因,一种替代方法是创建一个CNAME与组合(即建立了一个从域名指向另一个别名DNS记录)Aliasmod_rewrite

  1. 使用 Ajax Cacheable
    Ajax的一个引人注意的好处是它为用户提供即时反馈,因为它从后端Web服务器异步请求信息。但是,使用Ajax不能保证用户不会等待他们等待异步JavaScript和XML响应返回的大拇指。在许多应用中,用户是否保持等待取决于Ajax的使用方式。例如,在基于Web的电子邮件客户端中,用户将不断等待Ajax请求的结果来查找与其搜索条件匹配的所有电子邮件。重要的是要记住,“异步”并不意味着“瞬时”。

为了提高性能,重要的是优化这些Ajax响应。提高Ajax性能的最重要的方法是使响应可缓存,如添加到期或缓存控制头。
一些其他规则也适用于Ajax:

  • Gzip组件
  • 减少DNS查找
  • 缩小JavaScript
  • 避免重定向
  • 配置ETag

我们来看一个例子。
Web 2.0电子邮件客户端可能会使用Ajax下载用户的自动完成地址簿。
如果用户上次使用电子邮件网络应用程序后用户没有修改她的地址簿,如果Ajax响应可以使用未来的Expires或Cache-Control标头进行缓存,则可以从缓存读取以前的地址簿响应。必须通知浏览器何时使用先前缓存的地址簿响应,而不是请求新的地址簿响应。这可以通过向地址簿Ajax
URL添加一个时间戳来表示,例如,用户最后一次修改她的地址簿&t=1190241612。如果地址簿自上次下载以来没有被修改,则时间戳将是相同的,并且地址簿将从浏览器的缓存中读取,从而消除额外的HTTP往返。

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

  1. 后负载组件
    你可以仔细看看你的页面,问问自己:“为了最初渲染页面绝对需要什么?”
    其余的内容和组件可以等待。

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

帮助您解决问题的工具:YUI Image
Loader允许您将图像延迟到折叠位置,YUI
Get实用程序是一个简单的方法,可以即时包括JS和CSS。举个例子,在野外看看
Yahoo!主页与Firebug的网络面板打开了。

当性能目标与其他Web开发最佳实践相一致时,这是很好的。
在这种情况下,渐进增强的想法告诉我们,当JavaScript被支持时,可以改善用户体验,但是您必须确保页面的工作即使没有JavaScript。
所以在确定页面工作正常之后,您可以使用一些后加载脚本来增强它,从而为您提供更多铃声和口哨,如拖放和动画。

  1. 预加载组件
    预加载可能看起来与后期加载相反,但实际上具有不同的目标。通过预加载组件,您可以利用浏览器空闲的时间,并请求将来需要的组件(如图像,样式和脚本)。这样当用户访问下一页时,您可以将大部分组件放在缓存中,并且您的页面将为用户加载更快。

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

  • 无条件预 加载 – 一旦加载启动,您就可以继续提取一些额外的组件。
    检查google.com,了解如何请求一个精灵图像的加载。
    这个精灵图片不需要在google.com主页上,但在连续的搜索结果页面上是需要的。
  • 有条件的预加载 –
    基于用户操作,您做出有根据的猜测,用户在哪里下一步,并相应地预加载。在search.yahoo.com上,您可以看到在输入框中输入后,如何请求一些额外的组件。
  • 预计预加载 – 在启动重新设计之前提前预加载。
    经常重新设计后,您会发现:“新网站很酷,但比以前更慢”。
    问题的一部分可能是用户正在使用完整缓存访问您的旧站点,但新的站点始终是空缓存体验。您可以在启动重新设计之前预先加载某些组件来减轻这种副作用。您的旧网站可以使用浏览器空闲的时间,并请求新网站将使用的图像和脚本
  1. 减少DOM元素的数量
    复杂的页面意味着更多的字节下载,也意味着JavaScript中的DOM访问速度较慢。如果您想要添加事件处理程序,例如,如果循环访问500或5000个页面上的DOM元素,这将有所作为。

大量的DOM元素可能是一些症状,应该使用页面的标记进行改进,而不必删除内容。您是否使用嵌套表进行布局?你是否<div>只投入更多的东西来解决布局问题?也许有更好的和更语义上正确的方式来做你的标记。

对于布局来说,很大的帮助是YUI
CSS实用程序:grids.css可以帮助您整体布局,fonts.css和reset.css可以帮助您剥离浏览器的默认格式。这是一个机会,开始新鲜和思考你的标记,例如,<div>只有当它有意义的语义,而不是因为它呈现一个新的行。

DOM元素的数量很容易测试,只需输入Firebug的控制台:

 document.getElementsByTagName('*').length

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

  1. 分割跨域的组件
    分割组件允许您最大程度地并行下载。由于DNS查询损失,请确保您使用的不超过2-4个域。例如,您可以承载你的HTML和动态内容www.example.org之间分裂静电元件static1.example.org和static2.example.org

有关更多信息,请参阅Tenni Theurer和Patty
Chi的“最大化拼车车道中的并行下载
”。

  1. 最小化iframe的数量
    iframe允许在父文档中插入一个HTML文档。了解iframe的工作原理,以便有效的使用非常重要。
  • <iframe> 优点:
    帮助缓慢的第三方内容,如徽章和广告
    安全沙箱
    并行下载脚本

  • <iframe> 缺点:
    成本高,即使空白
    阻止页面加载
    非语义

  1. 没有404s
    HTTP请求是昂贵的,所以发出HTTP请求并获得无用的响应(即404 Not
    Found)是完全不必要的,并且会减慢用户体验,没有任何好处。

一些网站有帮助404s“你的意思是X?”,这对用户体验非常好,但也会浪费服务器资源(如数据库等)。特别糟糕的是当链接到外部JavaScript是错误的,结果是404.首先,这个下载将阻止并行下载。接下来,浏览器可能会尝试解析404响应体,就像它是JavaScript代码,试图找到可用的东西。


雅虎前端优化35条规则翻译

虽然在我们每天的工作生活中,浏览器给我们制造麻烦,使我们头疼,但请记住,他们也是很聪明的;
它们为我们做了很多性能优化工作,
所以大量的性能调优知识不但要知道浏览器在哪里给我们做了优化,还要知道怎么更好的挖掘它们。大量性能调优诀窍只是理解,利用和操纵浏览器已经替我们做好的优化工作。

1.5 延迟加载组件

你可以自习看看你的页面并问问你自己,最初页面的渲染需要什么,其他的内容和组件就是可以延迟加载的。

JavaScript是在 onload
时间之前和之后拆分的理想候选者,例如,如果您有拖放和动画的JS代码,则可以延迟加载,因为它需要在页面渲染完之后才可以执行。其它可延迟的包括隐藏的内容,折叠起来的图片等等。

Server

1. Content

顶部的Styles, 底部的scripts

1.6 预加载组件

预加载看起来和延迟加载相反,但它实际上有着不同的目标,通过预加载组件,您可以利用浏览器空闲的时间并请求将来需要的组件(如图像,样式和脚本)。这样,当用户访问下一页时,您可以将大部分组件放在缓存中,并且用户加载页面将更快。

有几种预加载类型:

  • 无条件预加载:一旦onload触发,你立即获取另外的组件。比如谷歌会在主页这样加载搜索结果页面用到的雪碧图。
  • 有条件预加载:基于用户操作,您可以进行有根据的猜测,即用户前进的位置并相应地预加载。
  • 预期的预加载:在旧网页预加载新网页的部分组件,那么切换到新网页时就不会是没有任何缓存了。

1.1 Make Fewer HTTP Requests

Minimize HTTP Requests减少/最小化 http 请求数。

到终端用户的响应时间80%花在前端:大部分用于下载组件(js/css/image/flash等等)。减少组件数就是减少渲染页面所需的http请求数。这是更快页面的关键。

减少组件数的一个方法就是简化页面设计。保持富内容的页面且能减少http请求,有以下几个技术:

  • Combined
    files。合并文件,如合并js,合并css都能减少请求数。如果页面间脚本和样式差异很大,合并会更具挑战性。
  • CSS Sprites。雪碧图可以合并多个背景图片,通过background-image
    background-position 来显示不同部分。
  • Image
    maps。合并多个图片到一个图片,一般用于如导航条。由于定义坐标的枯燥和易错,一般不推荐
  • Inline images。使用data:url scheme来內连图片。

减少请求数是为第一次访问页面的用户提高性能的最重要的指导。

这真的是一条基本规则,每个人都能非常容易的在大多数时间遵守,但为什么它重要?简短的说:

1.7 减少DOM数量

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

1.2 Reduce DNS Lookups

减少DNS查询。

就像电话簿,你在浏览器地址栏输入网址,通过DNS查询得到网站真实IP。

DNS查询被缓存来提高性能。这种缓存可能发生在特定的缓存服务器(ISP/local
area
network维护),或者用户的计算机。DNS信息留存在操作系统DNS缓存中(在windows中就是
DNS Client Serve
)。大多浏览器有自己的缓存,独立于操作系统缓存。只要浏览器在自己的缓存里有某条DNS记录,它就不会向操作系统发DNS解析请求。

IE默认缓存DNS记录30分钟,FireFox默认缓存1分钟。

当客户端的DNS缓存是空的,DNS查找次数等于页面中的唯一域名数。

减少DNS请求数可能会减少并行下载数。避免DNS查找减少响应时间,但减少并行下载数可能会增加响应时间。指导原则是组件可以分散在至少2个但不多于4个的不同域名。这是两者的妥协。

  • CSS 块渲染,
    因此你需要立即处理它(即在文档的顶部,在你的<head>之中)。
  • JS 块下载,
    因此你需要最后处理它们,以确保它们没有耽误页面中任何其它东西。

1.8 跨域拆分组件

拆分组件来达到最大化的并行下载,由于DNS查询的副作用,最好保证使用的域名不准超过2-4个。例如,您可以托管HTML和动态内容,www.example.org
并在static1.example.org和之间拆分静态组件。

1.3 Avoid Redirects

避免跳转。

跳转用301302状态码来达成。一个301响应http头的例子:

HTTP/1.1 301 Moved Permanently

Location: http://example.com/newuri

Content-Type: text/html

浏览器自动跳转到Location指定的路径。跳转所需的所有信息都在http头,所以http主体一般是空的。301
302响应一般不会被缓存,除非有额外的头部信息,比如ExpiresCache-Control指定要缓存。meta刷新标签或
JavaScript
也可以跳转,但如果真要跳转,3xx跳转更好,主要是保证返回键可用。

跳转显然拖慢响应速度。在跳转的页面被获取前浏览器没什么能渲染,没什么组件能下载。

最浪费的跳转之一发生在url尾部slash(/)缺失。比如http://astrology.yahoo.com/astrology301跳转到http://astrology.yahoo.com/astrology/。这可以被Apache等服务器修复,用Aliasmod_rewrite等等。

CSS块渲染是因为浏览器总是试图渐进式的渲染页面;它们想在元素到达的时候顺序的渲染它。如果style在距离很远的页面下部,浏览器在获得它之前没有办法渲染那个CSS。因为这个原因,如果浏览器在渲染文档过程中,改变了之前渲染的东西,它们可以避免style的重绘。浏览器在它获得所有需要的style信息之前不会渲染页面,如果你将style放在文档底部,你就是在使浏览器等待,阻塞了渲染。

1.9 最少的iframe

iframe允许html文档被插入到父文档。

<iframe>优点:

  • 帮助解决缓慢的第三方内容的加载,如广告和徽章
  • 安全沙盒
  • 并行下载脚本

<iframe>缺点:

  • 即使空的也消耗
  • 阻塞了页面的onload
  • 非语义化

1.4 Make Ajax Cacheable

让Ajax可缓存。

使用ajax的好处是可以向用户提供很快的反馈,因为它是向后台异步请求数据。但是,这些异步请求不保证用户等待的时间——异步不意味着瞬时。

提高ajax性能的最重要的方法是让响应被缓存,即在Add an Expires or a
Cache-Control
Header中讨论的
Expires 。其它方法是:

  • gzip组件
  • 减少DNS查找
  • 压缩JS
  • 避免跳转
  • 设置ETags

所以,只要你将CSS放在页面的顶部,那么浏览器就可以立刻开始渲染。

1.10 不要出现404

HTTP的请求是非常昂贵的,因此发出的HTTP请求获得无用的响应是完全没有必要的,并且会影响用户体验。

一些网站会有特别的404页面提高用户体验,但这仍然会浪费服务器资源。特别坏的是当链接指向外部js但却得到404结果。这样首先会降低并行下载数,其次浏览器可能会把404响应体当作js来解析,试图从里面找出可用的东西。

1.5 Post-load Components

延迟加载组件。

再看看你的页面然后问问自己,“什么是页面初始化必须的?”。剩下的内容和组件可以延迟。

JavaScript是理想的(延迟)候选者,可以切分到onload事件之前和之后。比如拖放的js库可以延迟,因为拖动必须在页面初始化之后。其它可延迟的包括隐藏的内容,折叠起来的图片等等。

JavaScript块下载是由于好几个原因(这又是浏览器聪明之处),但首先我们需要知道浏览器里的资源下载是如何实际发生的;简单的说,浏览器会从一个单一的域名并行的尽可能多的下载资源。它从越多的域名下载,就能在一瞬间并行的获得更多的资源。

2.1 使用CDN

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

CDN是一群不同地点的服务器,可以更高效地分发内容到用户。

1.6 Preload Components

预加载组件。

预加载看起来与延迟加载相反,但它的确有个不同的目标。通过预加载你可以利用浏览器的空闲时间来请求你将来会用到的组件。这样当用户访问下一个页面时,你会有更多的组件已经在缓存中,这样会极大加快页面加载。

有几种预加载类型:

  • 无条件预加载:一旦onload触发,你立即获取另外的组件。比如谷歌会在主页这样加载搜索结果页面用到的雪碧图。
  • 有条件预加载:基于用户动作,你推测用户下一步会去哪里并加载相应组件。
  • 预期的预加载:在发布重新设计(的网站)前提前加载。在旧网页预加载新网页的部分组件,那么切换到新网页时就不会是没有任何缓存了

JavaScript中断了这个过程,阻塞了从任何一个域名的并行的下载,因为:

2.2 添加Expries 或者 Cache-Control

这条规则有两个方面:

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

页面内容越来越丰富,意味着页面中有更多脚本,样式表,图像以及Flash。您的页面的首次访问可能必须发出多个HTTP请求,但通过使用Expires标头,您可以使这些组件可缓存。

浏览器使用缓存来减少HTTP请求的数量和大小,从而加快网页加载速度。Web服务器使用HTTP响应中的Expires头来告诉客户端可以缓存组件多长时间。
比如:

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

表示在2010-04-15都可以请求缓存内容。

1.7 Reduce the Number of DOM Elements

减少dom数。

一个复杂的页面意味着更多的内容要下载,以及更慢的dom访问。比如在有500dom数量的页面添加事件处理就和有5000dom数量的不同。

如果你的页面dom元素很多,那么意味着你可能需要删除无用的内容和标签来优化。

  • 被调用的脚本可能改变页面,即浏览器在继续别的事情以前,将不得不处理它。因此为了处理那个不测事件,浏览器停止了任何其它东西的下载,以便集中精力关注于它。
  • 脚本正常工作经常需要依照一定的顺序加载,例如,要在加载一个插件之前加载jQuery。浏览器阻止了JavaScript的并行下载,因此它不会同时下载jQuery和你的插件;很显然如果你同时并行下载二者,你的插件会在jQuery之前到达。

2.3 Gzip组件

通过前端工程师做出的决策,可以显著减少在网络上传输HTTP请求和响应所需的时间。从HTTP
/ 1.1开始,Web客户端表示支持使用HTTP请求中使用Accept-Encoding进行压缩。

 Accept-Encoding:gzip,deflate

如果服务器看到这个头部,它可能会选用列表中的某个方法压缩响应。服务器通过Content-Encoding头部提示客户端:

Content-Encoding: gzip

gzip一般可减小响应的70%。尽可能去gzip更多类型的文件。html,脚本,样式,xml和json等等都应该被gzip,而图片,pdf等等不应该被gzip,因为它们本身已被压缩过,gzip压缩它们只是浪费cpu,甚至增加文件大小。

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

1.8 Split Components Across Domains

把组件分散到不同的域名。

把组件分散到不同的域名允许你最大化并行下载数。由于DNS查询的副作用,最佳的不同域名数是2-4。

所以,由于浏览器在获取JavaScript的时候停止了所有其他下载,将你的JavaScript脚本放在文档中尽可能晚加载的地方是一个好主意。我相信你们都看到过页面中的空白片段,在那里第三方的JS脚本被花时间加载,并且它还阻止了页面其他资源的获取和渲染;这就是JavaScript的阻塞在作用了。

2.4 配置ETag

实体标记是Web服务器和浏览器用于确定浏览器缓存中的组件是否与源服务器上的组件匹配的机制。
添加ETag以提供验证比上次修改日期更灵活的实体的机制。ETag是唯一标识组件的特定版本的字符串。
服务器这样设置组件的ETag:

HTTP/1.1 200 OKLast-Modified: Tue, 12 Dec 2006 03:03:59 GMTETag: "10c24bc-4ab-457e1c1f"Content-Length: 12195

之后,如果浏览器要验证组件,它用If-None-Match头部来传ETag给服务器。如果ETag匹配,服务器返回304:

GET /i/yahoo.gif HTTP/1.1Host: us.yimg.comIf-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMTIf-None-Match: "10c24bc-4ab-457e1c1f"HTTP/1.1 304 Not Modified

1.9 Minimize the Number of iframes

最小化iframe的数量。

iframe允许html文档被插入到父文档。

<iframe>优点:

  • 帮助解决缓慢的第三方内容的加载,如广告和徽章
  • 安全沙盒
  • 并行下载脚本

<iframe>缺点:

  • 即使空的也消耗(资源和时间)
  • 阻塞了页面的onload
  • 非语义化(标签)

但是显然,现代浏览器还是变得聪明了。我将给你一个Andy
Davies寄给我的电子邮件的摘录,因为他解释的比我清楚:

2.5 尽早刷新Buffer

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

一个比较好的flush的位置是在head之后,因为浏览器可以加载其中的样式和脚本文件,而后台继续生成页面剩余部分。

<!-- css, js --></head><?php flush(); ?><body><!-- content -->

1.10 No 404s

不要404。

http请求是昂贵的,所以发出http请求但获得没用的响应(如404)是完全不必要的,并且会降低用户体验。

一些网站会有特别的404页面提高用户体验,但这仍然会浪费服务器资源。特别坏的是当链接指向外部js但却得到404结果。这样首先会降低(占用)并行下载数,其次浏览器可能会把404响应体当作js来解析,试图从里面找出可用的东西。

现代浏览器将并行下载JS,只有在脚本被执行的时候阻塞渲染(显然脚本必须也被下载了)。脚本下载常常被浏览器的预加载器所完成。当浏览器页面渲染被阻塞,即等待CSS,或JS被执行,预分析器将扫描页面剩余部分,寻找它能下载的资源。有些浏览器如
Chrome,
将分先后下载资源,例如,如果脚本与图片同时在等待下载,它将先下载脚本。

2.6 AJAX 使用 GET 请求

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

POST不提交任何数据跟GET行为类似,但从语义上讲,获取数据应该用GET,提交数据到服务器用POST。

2. Server

漂亮的内容!

2.7 避免空src的图片

空src属性的图片的行为可能跟你预期的不一样。它有两种形式:

  1. html标签:<img src="">
  2. js:var img = new Image(); img.src = "";

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

  • Internet Explorer向页面所在的目录发出请求。
  • Safari和Chrome会向实际页面提出请求。
  • Firefox
    3及更早版本的行为与Safari和Chrome相同,但3.5版解决了此问题[错误444931],不再发送请求。
  • 遇到空图像时,Opera不执行任何操作。
  1. 由于发送大量的意料之外的流量,会削弱服务器,尤其那些每天pv上百万的页面。
  2. 浪费服务器计算周期取生成不会被浏览的页面。
  3. 可能会破坏用户数据。如果你在跟踪请求状态,通过cookie或其它,你可能会破坏数据。即使image的请求不会返回图片,但所有的头部数据都被浏览器读取了,包括cookie。即使剩下的响应体被丢弃,破坏可能已经发生。

2.1 Use a Content Delivery Network

使用CDN。

用户接近你的服务器会减少响应时间。把你的内容发布到多个,地理上分散的服务器可以让页面加载更快。但怎么开始?

首先不要试图把你的架构重新设计成分布式架构。因为可能引进更多复杂性和不可控。

记住80-90%的终端用户响应时间花费在下载页面中的所有组件:图片、样式、脚本、falsh等等。这是Performance
Golden
Rule
。不要从困难的重新设计后台架构开始,最好首先分发你的静态内容。这不仅可以减少响应时间,用CDN还很容易来做。

CDN是一群不同地点的服务器,可以更高效地分发内容到用户。一些大公司有自己的CDN。

所以,要使页面被尽可能快的渲染,将styles放在顶部。为了阻止JS的阻塞影响到渲染,将scripts放在底部。

3.1 减小Cookie大小

http
cookie的使用有多种原因,比如授权和个性化。cookie的信息通过http头部在浏览器和服务器端交换。尽可能减小cookie的大小来降低响应时间。

  • 消除不必要的cookie。
  • 尽可能减小cookie的大小来降低响应时间。
  • 注意设置cookie到合适的域名级别,则其它子域名不会被影响。
  • 正确设置Expires日期。早一点的Expires日期或者没有会尽早删除cookie,优化响应时间。

2.2 Add an Expires or a Cache-Control Header

Expires或者Cache-Control头部。

这条规则有两个方面:

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

页面越来越丰富,意味着更多脚本,样式,图片等等。第一次访问的用户可能需要发出多个请求,但使用Expires可以让这些组件被缓存。这避免了访问子页面时没必要的http请求。Expires一般用在图片上,但应该用在所有的组件上。

浏览器(以及代理)使用缓存来减少http请求数,加快页面加载。服务器使用http响应的Expires头部来告诉客户端一个组件可以缓存多久。比如下面:

Expires: Thu, 15 Apr 2010 20:00:00 GMT //2010-04-15

注意,如果你设置了Expires头部,当组件更新后,你必须更改文件名。

更少的请求

3.2 用没有cookie的域名提供组件。

当浏览器发出静态图像请求并将cookie与请求一起发送时,服务器对这些cookie没有任何用处。所以他们只是没有充分理由创建网络流量。您应该确保使用无cookie请求请求静态组件。创建一个子域并在那里托管所有静态组件。

如果您的域名是www.example.org,您可以托管您的静态组件static.example.org。但是,如果您已经在顶级域上设置了cookie
example.org而不是www.example.org,则所有请求都
static.example.org将包含这些cookie。在这种情况下,您可以购买一个全新的域,在那里托管您的静态组件,并保持此域无cookie

2.3 Gzip Components

传输时用gzip等压缩组件。

http请求或响应的传输时间可以被前端工程师显著减少。终端用户的带宽,ISP,接近对等交换点等等没法被开发团队控制,但是,压缩可以通过减少http响应的大小减少响应时间。

HTTP/1.1开始,客户端通过http请求中的Accept-Encoding头部来提示支持的压缩:

Accept-Encoding: gzip, deflate

如果服务器看到这个头部,它可能会选用列表中的某个方法压缩响应。服务器通过Content-Encoding头部提示客户端:

Content-Encoding: gzip

gzip一般可减小响应的70%。尽可能去gzip更多(文本)类型的文件。html,脚本,样式,xml和json等等都应该被gzip,而图片,pdf等等不应该被gzip,因为它们本身已被压缩过,gzip它们只是浪费cpu,甚至增加文件大小。

另一个明显而基本的性能优化方法是少下载。页面需要的每一个资源就是一次额外的HTTP请求;浏览器不得不停下来去获取每一个用于渲染页面所需的资源。每一次HTTP请求都可能引发DNS查询,重定向,404,等等。每一次HTTP请求,无论为了样式表,图片,web字体,JS文件还是其它你能想到的,都可能是一次非常昂贵的操作。尽量减少这些请求是你可以做的最快的优化方法中的一种.

4.1 将CSS放在顶部

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

关注性能的前端工程师希望页面被逐步渲染,这时因为,我们希望浏览器尽早渲染获取到的任何内容。这对大页面和网速慢的用户很重要。给用户视觉反馈,比如进度条的重要性已经被大量研究和记录。在我们的情况中,HTML页面就是进度条。当浏览器逐步加载页面头部,导航条,logo等等,这些都是给等待页面的用户的视觉反馈。这优化了整体用户体验。

把样式表放在文档底部的问题是它阻止了许多浏览器的逐步渲染,包括IE。这些浏览器阻止渲染来避免在样式更改时需要重绘页面元素。所以用户会卡在白屏。

2.4 Configure ETags

实体标记(Entity
tags,ETag)是服务器和浏览器之间判断浏览器缓存中某个组件是否匹配服务器端原组件的一种机制。实体就是组件:图片,脚本,样式等等。ETag被当作验证实体的比最后更改(last-modified)日期更高效的机制。服务器这样设置组件的ETag:

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:

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将不匹配。然而服务器集群是处理请求的通用解决方案。

如果不能解决多服务器间的ETag匹配问题,那么删除ETag可能更好。

再谈到浏览器和并行;大多数浏览器一次只从每个引用的域下载一些资源,而JS会阻塞这些下载。所以,你做的每一个HTTP请求都应该仔细考虑,而不是随便随便做的。

4.2 避免CSS表达式

CSS表达式是强大的设置动态CSS属性的方法。IE5开始支持,IE8开始不赞成使用。例如,背景颜色可以设置成每小时轮换:

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

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

2.5 Flush the Buffer Early

早一点刷新buffer(尽早给浏览器数据)。

当用户请求一个页面,服务器一般要花200-500ms来拼凑整个页面。这段时间,浏览器是空闲的(等数据返回)。在php,有个方法flush()允许你传输部分准备好的html响应给浏览器。这样的话浏览器就可以开始下载组件,而同时后台可以继续生成页面剩下的部分。这种好处更多是在忙碌的后台或轻前端网站可以看到。

一个比较好的flush的位置是在head之后,因为浏览器可以加载其中的样式和脚本文件,而后台继续生成页面剩余部分。

<pre style=”background:#F6F8FA;box-sizing: border-box;word-wrap:
normal;
border-radius: 3px;overflow:auto”></pre>

<pre style=”background:#F6F8FA”></head></pre>

<pre style=”background:#F6F8FA”><?php flush();
?></pre>

<pre style=”background:#F6F8FA”><body></pre>

<pre style=”background:#F6F8FA”></pre>

尽可能并行

4.3 选择<link>而不是@import

之前的一个最佳原则是说CSS应该在顶部来允许逐步渲染。

在IE用@import和把CSS放到页面底部行为一致,所以最好别用。

2.6 Use GET for AJAX Requests

ajax请求用get。

Yahoo!
Mail团队发现当使用XMLHttpRequest,POST
被浏览器实现为两步:首先发送头部,然后发送数据。所以使用GET最好,仅用一个TCP包发送(除非cookie太多)。IE的url长度限制是2K。

POST但不提交任何数据根GET行为类似,但从语义上讲,获取数据应该用GET,提交数据到服务器用POST。

为了让浏览器能并行的下载更多资源,你可以由不同的域名提供服务。如果说,浏览器只能一次从一个域名获取两个资源,那么由两个域名提供服务意味着它可以一次性获取四个资源;三个域名意味着六个并行下载。

发表评论

电子邮件地址不会被公开。 必填项已用*标注