从雅虎军规看前端性能优化

从雅虎军规看前端性能优化

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

1. Content

1.1 最小化HTTP请求

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

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

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

1.2 减小DNS查找

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

经过缓存DNS查找来得到更好的性能。DNS信息保留在操做系统的DNS缓存中,大多数的浏览器都有本身的缓存,与操做系统的分开。express

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

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

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

1.3 避免重定向

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

HTTP/1.1 301 Moved Permanently
Location: http://example.com/newuri
Content-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/

1.4 使Ajax可缓存

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

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

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

1.5 延迟加载组件

你能够自习看看你的页面并问问你本身,最初页面的渲染须要什么,其余的内容和组件就是能够延迟加载的。

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

1.6 预加载组件

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

有几种预加载类型:

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

1.7 减小DOM数量

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

1.8 跨域拆分组件

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

1.9 最少的iframe

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

<iframe>优势:

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

<iframe>缺点:

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

1.10 不要出现404

HTTP的请求是很是昂贵的,所以发出的HTTP请求得到无用的响应是彻底没有必要的,而且会影响用户体验。

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

2. Server

2.1 使用CDN

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

CDN是一群不一样地点的服务器,能够更高效地分发内容到用户。

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均可以请求缓存内容。

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,甚至增长文件大小。

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

2.4 配置ETag

实体标记(ETag)是Web服务器和浏览器用于肯定浏览器缓存中的组件是否与源服务器上的组件匹配的机制。 添加ETag以提供验证比上次修改日期更灵活的实体的机制。ETag是惟一标识组件的特定版本的字符串。 服务器这样设置组件的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

2.5 尽早刷新Buffer

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

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

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

2.6 AJAX 使用 GET 请求

在雅虎邮件团队发现,在使用时XMLHttpRequest,POST在浏览器中实现为两步过程:首先发送头部,而后发送数据。所以最好使用GET,它只须要一个TCP数据包发送(除非你有不少cookie)。IE中的最大URL长度为2K,所以若是发送的数据超过2K,则可能没法使用GET。

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

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。即便剩下的响应体被丢弃,破坏可能已经发生。

3. Cookie

### 3.1 减少Cookie大小

http cookie的使用有多种缘由,好比受权和个性化。cookie的信息经过http头部在浏览器和服务器端交换。尽量减少cookie的大小来下降响应时间。

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

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

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

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

4. CSS

4.1 将CSS放在顶部

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

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

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

4.2 避免CSS表达式

CSS表达式是强大的(可能也是危险的)设置动态CSS属性的方法。IE5开始支持,IE8开始不同意使用。例如,背景颜色能够设置成每小时轮换:

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

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

4.3 选择<link>而不是@import

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

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

4.4 避免过滤器

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

最佳作法是放弃AlphaImageLoader,改用PNG8来优雅降级。

5. JavaScript

5.1 将Script放在底部

脚本引发的问题是它们阻塞了并行下载。 HTTP1.1规范建议浏览器每一个域名下不要一次下载超过2个组件。若是你的图片分散在不一样服务器,那么你能并行下载多个图片。但当脚本在下载,浏览器不会再下载其它组件,即便在不一样域名下。

有些状况下把脚本移动到底部并不简单。好比,脚本中用了document.write来插入内容,它就不能被移动到底部。另外有可能有做用域问题。但大多数状况,有方法能够解决这些问题。

一个替代建议是使用异步脚本。defer属性代表脚本不包含document.write,是提示浏览器继续渲染的线索。

5.2 使用外部JavaScript 和 CSS

在实际中使用外部文件一般会产生更快的页面,由于浏览器会缓存JavaScript和CSS文件。每次请求HTML文档时,都会下载HTML文档中内联的JavaScript和CSS。这减小了所需的HTTP请求数,但增长了HTML文档的大小。另外一方面,若是JavaScript和CSS位于浏览器缓存的外部文件中,则HTML文档的大小会减小,而不会增长HTTP请求的数量。

5.3 压缩JavaScript 和 CSS

压缩就是删除代码中没必要要的字符来减少文件大小,从而提升加载速度。当代码压缩时,注释删除,不须要的空格(空白,换行,tab)也被删除。

5.4 删除重复的脚本

在一个页面中两次包含相同的JavaScript文件会损害性能。这并不像你想象的那么不寻常。对美国十大顶级网站的评论显示,其中两个网站包含重复的脚本。两个主要因素会增长脚本在单个网页中重复的概率:团队规模和脚本数量。当它发生时,重复的脚本会经过建立没必要要的HTTP请求和浪费的JavaScript执行来损害性能。

发出没必要要的http请求发生在IE而不是Firefox。在IE,若是外部脚本引入两次且没有缓存,它会发出2个请求。即便脚本被缓存,刷新时也会发出额外请求。

除了增长http请求,时间被浪费在执行脚本屡次上。无论IE仍是Firefox都会执行屡次。

5.5 最小化DOM访问

使用JavaScript访问DOM元素的速度很慢,所以为了得到响应更快的页面,您应该:

  • 缓存访问过的元素的引用
  • 在DOM树外更新节点,而后添加到DOM树
  • 避免用JS实现固定布局

5.6 使用事件代理

有时候页面看起来不那么响应(响应速度慢),是由于绑定到不一样元素的大量事件处理函数执行太屡次。这是为何使用_事件委托_是一种好方法。

另外,你没必要等到onload事件来开始处理DOM树,DOMContentLoaded更快。大多时候你须要的只是想访问的元素已在DOM树中,因此你没必要等到全部图片被下载。

6. images

6.1 优化图片

  • 检查GIF并查看它们是否使用与图像中颜色数对应的调色板大小。
  • 能够把gif转成png看看有没有变小。除了动画,gif通常能够转成png8
  • 运行pngcrush或其它工具压缩png。
  • 运行jpegtran或其它工具压缩jpeg。

6.2 优化CSS精灵图

  • 将图像水平排列在精灵图中而不是垂直排列一般会致使文件较小。
  • 把颜色近似的图片合并到一张精灵图,这样可让颜色数更少,若是低于256就能够用png8.
  • “适应移动设备”而且不要在精灵中留下大的间隙。这不会影响文件大小,但须要较少的内存,以便用户代理将图像解压缩为像素图。

6.3 不要在HTML中缩放图片

不要使用比您须要的更大的图像,由于您能够在HTML中设置宽度和高度。若是您须要, <img width="100" height="100" src="mycat.jpg" alt="My Cat" />  那么您的图像(mycat.jpg)应该是100x100px而不是缩小的500x500px图像。

6.4 让 favicon.ico 小且可缓存

favicon.ico是在你服务器根路径的图片。邪恶的是即便你不关心它,浏览器仍然会请求它。因此最好不要响应404。另外因为在同一服务器,每次请求favicon.ico时也会带上cookie。这个图片还会影响下载顺序,好比在IE,若是你在onload时下载额外的组件,fcvicon会在这些组件以前被下载。

怎么减轻favicon.ico的缺点?

  • 小,最好1K如下
  • 设置Expires头部。也许能够安全地设置为几个月。

7. Mobile

7.1 保持组件小于25K

此限制与iPhone不会缓存大于25K的组件这一事实有关。请注意,这是未压缩的大小。在这里减小组件大小很重要,由于单独使用gzip可能还不够。

7.2 将组件打包到多部分文档中

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

相关文章
相关标签/搜索