1、减少HTTP请求
80%的终端用户响应时间花在了前台。其中,大部分时间都用于下载页面中的各种组件——图像、样式表、脚本、Flash等等。因此,减少组件的数量就能够减少呈现页面所需的HTTP请求数量。这正是加速网页显示的关键所在。
减少页面中组件的一种思路是简化页面的设计。然而,是否存在一种既能使页面内容丰富,又可以加速响应时间的方案呢?以下就是一些既能够减少HTTP请求数量,又可以确保页面内容丰富的技术。
通过图像地图将多幅图像组合为一幅图像。这样一来,虽然整体尺寸相同,但可以减少HTTP请求,进而加速页面显示。不过,图像地图只适用于页面中连续的图像,比如导航条。而且,定义图像地图中的坐标值通常会令人头疼,也容易出错。
- 未使用图像地图的例子:http://stevesouders.com/hpws/imagemap-no.php
- 使用了图像地图的例子:http://stevesouders.com/hpws/imagemap.php
“CSS精灵”是减少图像请求次数的首选方法。所谓“CSS精灵”,就是将页面中要用到的所有图像都组合到一幅图像中,然后通过CSS中的background-image和background-position属性,按照需要显示这幅图像中的不同部分。
- 使用CSS精灵的例子:http://stevesouders.com/hpws/sprites.php
- 推荐一个经典的例子:http://www.cssplay.co.uk/menu/streaker(别忘了“查看源代码”!)
使用data: URL模式在实际的页面中嵌入图像数据。不过,这种方案会增大HTML文档的尺寸。因此,将嵌入图像与(缓存的)样式表结合使用,是一种既能减少HTTP请求,又可以避免增大页面尺寸的方法。
data:URL模式提出于1995年,相应的规范地址为:http://tools.ietf.org/html/rfc2397 。使用格式为:
data:[<mediatype>][;base64],<data>
嵌入的红星图像可以像下面这样指定:
<IMG ALT=”Red Star”
src=”data:image/gif;base64,R0lGODlhDAAMALMLAPN8ffBiYvWW
lvrKy/FvcPewsO9VVfajo+w6O/zl5estLv/8/AAAAAAAAAAAAAAAACH5BAEA
AAsALAAAAAAMAAwAAAQzcElZyryTEHyTUgknHd9xGV+qKsYirKkwDYiKDBia
tt2H1KBLQRFIJAIKywRgmhwAIlEEADs=”>
使用嵌入图像的问题是,IE(直至IE7)不支持嵌入图像;另外,Firefox将嵌入图像的大小限制为100K。虽然使用64位编码可以不仅会增大图像尺寸,但而且也会增加相应的下载时间。
- 使用嵌入图像的例子:http://stevesouders.com/hpws/inline-images.php
- 在CSS中使用嵌入图像的例子:http://stevesouders.com/hpws/inline-css-images.php
另外,整合文件也是减少HTTP请求数量的一种方案。比如,可以把所有脚本都整合到一个脚本文件中。类似地,也可以把所有样式表都整合到一个样式表中。实际上,整合文件是一种尚未见到广泛应用的简单思路。在美国前10大网站中,每个页面平均包含七个脚本和两个样式表。当希望整合的脚本和样式表在不同页面之间有所差别的情况下,整合文件也将面临挑战。但是,即使在最终发布的网站中只能整合一部分文件,也能够起到改善响应时间的作用。
减少页面中HTTP请求的数量是改善前端性能的出发点。而且也是针对首次访问用户改善网站性能的最重要方针。正如Tenni Theurer在他的博客文章Browser Cache Usage – Exposed!中所揭示的:在你网站的日常访问者当中,40~60%访问者的缓存都是空的。因此,让自己的页面能够在这些首次访问的用户屏幕中快速地显示出来,是提升用户体验的关键。
---------------------------------------------------------------------------------------------------------------------------
From:http://blog.csdn.net/FrankTaylor
前端性能的重要性The Importance of Frontend Performance
我的大部分web生涯都是在扮演后台开发工程师的角色。所以,我很自然的把每个性能作业都作为是一个后台的优化练习罢了,像什么编译器参数,数据库索引,内存管理什么的。而且也有很多关于后台性能优化的书籍和资料让大家从中找到想要的东西。但实际上,对于绝大多数的web页面,只有不到10-20%的最终用户响应时间是花在了从服务器下载HTML源文件到用户浏览器上。如果你想达到不可思议般的用户快速浏览体验,那当然就应该去关注一下那其它的80-90%的用户体验时间花在哪儿呢?又该怎么去减少这个时间呢?后面的章节就会向您讲解与目前web优化所相关的一些基础知识,并提供14条优化性能的法则。
来关注一下web页面的性能
为了知道怎么去提高性能,我们应该先了解最终用户们都把等待的时间花在哪儿了?图A-1是在IE上访问Yahoo!的首页(http://www.yahoo.com)的HTTP响应时间图(John注:我们可以用HttpWatch(IE),Firebug(ff)工具来生成类似的图)。每一个横条都是一个HTTP请求。第一个横条,标识为html的那个,是HTML文档的初始请求(指请求HTML源文件)。然后浏览器解析这个HTML文档,并且开始下载这个页面的所有组件(John注:这里的组件是指页面所引用的图片,flash等非html文档的东西)。在我们的测试环境下,浏览器的缓存是空的,所以所有的组件都会被下载。在图上,我们可以看到,HTML源文件的下载只占整个响应时间的5%,最终用户花了近95%的时间用在等待下载组件上.还有一小部分是花在HTML,script和样式表(stylesheets)的解析上,在图中我们用每个下载时间条间的空白间隔来表示这些解析时间.
图A-2显示的是我们第二次用IE浏览这个网页时的情况.HTML文档的下载占到了整个响应时间的12%.大部分的组件都不用再下载了,因为它们已经被浏览器缓存了。
图A-1 在Internet Explorer上访问http://www.yahoo.com,空缓存
图A-2在Internet Explorer上访问http://www.yahoo.com,预先已有缓存
Ok,我们来看一下,有五个组件在第二次浏览页面时仍被下载了:
一个重定向(redirect)
这里的重定向虽然已在第一次访问被处理过了,但是浏览器还是再次请求了一次。因为它的HTTP响应状态码是302(表示"Found" 或 "move temporarily"),在响应header中没有缓存信息,所以浏览器不会去缓存它。关于这方面我们会在Chapter B中讨论HTTP时提到。
三个没有缓存的图片
接着的三个request请求是在上一次浏览时没有下载的三个图片。这些是经常变动的新闻图片和广告图片.
一个被缓存的图片
最后一个HTTP request请求是一个有条件的GET请求.这个图片是上次被缓存的,但是因为HTTP的响应头(response headers)的设置,浏览器要确认一下这个图片是不是最新的.有条件的GET请求我们也会在Chaptet B中讨论它.
时间都去哪儿了?
再回过来看看HTTP时间响应图,我们看到至少80%的最终用户响应时间是花在了下载页面里的组件上,如果我们来仔细分析一下这个图表的内容,我们会发现浏览器与HTTP之间的交互开始有点变的复杂了。除了上面我提到了HTTP的状态码和header会响应浏览器的缓存,另外,我们还能得到下面一些观察结果:
l 凡是被缓存的组件(图A-2)大多都不会有下载动作。相反,你看到的是紧跟在Html请求后的一个没有下载的空白时间间隔,这表示这段时间是在解析HTML,JavaScript和CSS,以及从缓存中获取相关的组件。
l 在同一时间里的HTTP请求数变化了。图A-2在同一个时间切面上最多只有三个HTTP请求,而图A-1却同时有多达六到七个HTTP请求。这是因为使用了多个不同的主机名(hostname),而无论它们是使用HTTP/1.0还是HTTP/1.1。Chapter 6将会解释这种多个同时下载的"平行下载(Parallel Downloads)"。(John注:是指同时下载)
l 这种平行下载不会发生在下载script上,因为在大多数情况下,浏览器会阻止其它下载script的HTTP请求。Chapter 6会解释为什么会这样,同时也会教你如何应用这个知识去优化你的页面载入时间。
要完完整整地指出时间都去哪儿了真是一个挑战。但至少还是很容易地能看到哪儿没花时间?它没有全花在下载HTML文档上,也没全花在后台的处理上。(几乎都花在了前端下载组件上)这就是为什么前端性能如此重要了。
性能黄金法则
像Yahoo!主页这样只有10%-20%的响应时间花在下载HTML源文件的现象并不是一个特例。据我分析,几乎所有与Yahoo!类似的网站都是这样(这可不包括Yahoo!Search,因为它的页面上组件的数量实在是太少了)。甚至可以进一步说,绝大多数的网站都是这样的情况。表A-1展示了由http://www.alexa.com所统计出的当今美国前10大网站。说明一下,下面提到的网站只有AOL不在前10,因为Craigslist.org本是排在前10,但是它的页面风格没有什么图片,script和样式表,不适合这里做为研究例子,所以我挑选了AOL。
图A-1 访问10大网站时的下载HTML源文件所占的时间比
所有的网站都只花了不到20%的总响应时间在获取HTML源文件上(John注:这一部分时间更多地取决于各网站的后端性能)。但只有Google在已有缓存的情况下是个例外。因为http://www.google.com只有6个组件,其中有5个被配置成被浏览器缓存。再次访问时,所有的组件被缓存,只有一个请求HTML源文件的HTTP请求和一个图片请求。
在做完所有的后台优化努力的情况下,你已经很难再有大的突破了。很显然,是时候关注前端的性能了。
首先,关注前端性能所能带来的整个性能提升到底有多少。如果我们能把后台的响应时间再优化,再砍掉一半响应时间,最终用户的响应时间也只是相应减少5% ~10%(John注:因为后台的性能只能是减少那个20%的响应HTML源文件请求)。相反的,如果我们把前端的性能提高一倍,我们可以把整个响应时间减少40~45%。
再说了,前端的改进一般不需要太多的时间和资源。而优化后台的性能时间基本上都得深入应用的构架和代码,找出优化的关健代码路径,增加或者改进硬件,分布化数据库等等,这些工作动辄就要以周和月为时间单位。在接下来的章节中介绍的前端性能优化法则都来自于最佳实践,比如修改web服务器的配置文件(Chapters3,4);将script和样式表放置到页面中相应的地方(Chapters 5 ,6);将图片,script,样式表组合到一起(Chapters 1)。这些实践只需要以小时和天为工作单位--远比提高后台性能需要的时间成本要低。
第三点,前端性能的这些实践都是经过实际考验的。在Yahoo!中有超过50个小组用这些实践减少了25%甚至更多的最终用户响应时间。在一些案例中,我们分析了运用这些要点的网站,一般都能达到25%或更多的性能提升。
在开始每个新的性能提升项目时,我都会画一张类似图A-1的图表来阐释一下性能的黄金法则:
只有10-20%的最终用户响应时间是花在了下载HTML源文件上。其它的80-90%是花在了下载页面中的所有组件上。
俺把这句浓缩一下,就是:80-90%的用户等待时间是来自于前端的页面加载。
这本书后面的部分将会提供详细的指导法则去减少这80-90%的最终用户响应时间。为了说明这些法则,我会陆续提到很多相关的技术:HTTP headers,JavaScript,CSS,Apache等等。
因为一些HTTP的基本概念对理解这本书非常有必要,所以我会在Chapter B中重点简介。
在这之后就是分章节的14条优化法则。我把这些法则按优先级列出。每条法则都有自己的适应范围。举个例子,法则2更适合商业网站而不适合个人站点。如果您应用所有适合您网站的的优化法则,您可以将页面速度提升25-50%从而增强用户体验。这本书的最后章节会告诉您如何以性能的眼光去分析美国的10大网站。
HTTP Overview
在开始介绍具体的优化法则之前,您务必要理解超文本传输协议:HyperText Transfer Protocol(HTTP)对性能的影响。HTTP是浏览器与服务器之间通过Internet通信的方式。HTTP的规范是由万维网联盟:W3C(World Wide Web Consortium)和互联网工程任务组:IETF(Internet Engineering Task Force)共同制定,而最终形成的RFC 2616规范。HTTP/1.1是目前流行通用的版本了,但还是有一些浏览器只支持HTTP/1.0。
HTTP就是描述请求request和响应response的c/s模型协议。一个浏览器发送HTTP请求(request)到一个指定的URL,这个 URL所指定的服务器接到请求后返回一个HTTP响应(response)给浏览器,就这么简单。与很多互联网服务一样,这个协议用的是简单的明文格式。请求的种类有:GET,POST,HEAD,PUT,DELETE,OPTIONS和TRACE。下面我只重点介绍GET请求,这一最常用的。
一个GET请求把所请求的URL组装在头信息(headers)中,然后发送到这个指定的URL。服务器接收到请求后,经过响应处理,返回一个包含状态码,头信息(headers)和具体明文文本(一般是Html源码)所组装的数据包。如下图,就是请求yahoo_2.0.0-b2.js时的HTTP头信息(headers)的内容示例。
压缩
如果浏览器和服务器都支持,可以通过压缩来减少响应返回时的数据量。浏览器通过头信息中的Accept- Encoding元素来告诉服务器是否可以接受压缩数据,以及何种压缩方式。而服务器则通过头信息中的Content-Encoding元素来告诉浏览器,我目前支持哪种压缩方式。如下图
注意上图中返回的数据是已经被压缩的数据。Chapter 4会专门介绍HTTP压缩,以及在代理缓存下产生的一些问题,当然还会讨论一些其它的头信息(headers)。
有条件的GET请求 Conditional GET Request
如果浏览器已经缓存了一个组件,但是浏览器该怎么知道这个组件是否还有效呢,于是就产生了有条件的GET请求。如果缓存里的组件是有效的,浏览器就继续使用这个组件来加载页面,以减少响应的数据量从而加速了用户体验。
一般来说,判断缓存的组件是否有效是检查它的最后修时间。浏览器通过response响应数据中名为Last-Modified的头信息来获取这个时间值。再次有相同组件的GET请求时,浏览器会将名为If-Modified-Since头信息随GET请求一起发送到服务器,带着这一条件信息给远程的服务器,这就好像是浏览器对服务器呐喊:"我已经有一个版本的组件了,这里它的最后修改时间,这次我还可以继续使用它吗?"(只要网络不断,服务器总是会听见这呐喊声的)
如果这个组件在这个Last-Modified描述的时间之后没有被修改过,服务器就不会返回这个组件的具体数据了,而返回一个"304 Not Modified"状态码,这样可不就提高了响应速度了。在HTTP/1.1里,名为ETag和If-None-Match的头信息也可以起到类似的作用,这两个都会在Chapter 13中有讨论。
过期 Expires
有条件的GET请求和返回304状态码能让页面载入的更快,但它还是需要在客户端和服务器端进行一个往返的验证过程,HTTP请求仍然存在。而名为Expires的头信息会则会避免这种验证过程。
一旦浏览器发现响应返回的头信息中有Expires属性,它就会把这个属性所描述的日期与组件保存到浏览器缓存中,只要再次访问这个组件时的日期没有超过Expires属性里描述的日期,就会一直被浏览器使用而不会再次发送HTTP请求。Chapter 3会有关于Expires和Cache-Control头信息的更多介绍。
Keep-Alive
HTTP是建立在TCP协议的上层的实现,在早期的HTTP实现中,每个HTTP请求都会打开一个新的socket连接。实际上效率很低,因为大多数的 HTTP请求都是针对同一个服务器发出的(想像一下我们浏览一个页面的情形,是不是该页面的组件大多数都是在这个页面所host的服务器上)。于是,长连接(persistent connections)的概念被引入了HTTP,以解决这种同一个服务器不停地打开关闭socket连接的情况。它能够让浏览器的多个请求只通过一个连接完成。浏览器和服务器就是通过相互传递Keep-Alive头信息来判断是否支持这一特性。
浏览器或服务器可以通过发送一个close头信息来关闭连接。从规范来说,keep-alive并不包含在HTTP/1.1中,但是绝大多数浏览器和服务器还是支持这一特性的。
Pipelining, 定义在HTTP/1.1中,它允许在一个socket连接中发送多个请求而不用等待响应返回。Pipelining比长连接(persistent connections)有着更好的性能。但是很不幸,IE不支持(IE7已经支持了),FireFox 2以后的版本虽然支持,但默认是关闭的。所以在Pipelining还没能普及以前,我们就还只能用Keep-Alive的方式来优化浏览器与服务器之间通过socket的通信。这个特性对于HTTPS很重要,因为HTTPS的连接都是长时间的连接.
更多
这个章节只是大致的介绍了HTTP,并把重点放在介绍影响性能的方面。如果要了解更多,您可以参考HTTP规范(http://www.w3.org/Protocols/rfc2616/rfc2616.html)和由David Gourley 与 Brian Totty编写的《HTTP: The Definitive Guide》(O'Reilly;http://www.oreilly.com/catalog/httptdg)。上面所例举的资料将会您理解我们后台的章节有很大的帮助。
法则 1: 尽可能减少HTTP请求数 Make Fewer HTTP Requests
在Chapter A中介绍的性能黄金法则,揭示了一个现象:只有10~20%的用户响应时间是花在请求html源文件上,剩下的80~90%的时间则是在请求页面中的各个组件(图片,script,样式表,flash等)。因此,我们的第一个提速的方法就是尽可能的减少这些组件的数量,我们的目的就是要减少HTTP请求的数量。
减少页面组件的建议,通常会让人在性能和产品设计上产生冲突。毕竟我们的页面现在所蕴含的元素越来越多,更多的小图片,不同的样式表,script等,这一章节,我会介绍一些技术方法来帮助我们平衡性能与产品设计上的冲突。这些将要出场的技术包括:image maps, CSS sprites,inline images以及尽量使用独立的js和样式表文件。使用这些技术方法在我们的案例中能减少50%的响应时间。
Image Maps
将一个页面中所要引用的图片整合成一个单一的图片文件,按顺序排好,再分切出里面的链接区域。这样对整个图片群的需求样式没有变,但减少了对图片的http请求数。
图1-1显示的是一个有五个图片组成的导航栏,每个图片对应一个独立的超链接。我们常规的做法,当然就是做五个图片,然后为每个图片做一个链接;但为了更高效,我们把五张独立的图片做成一张image map,这样从五个HTTP请求,就变成了一个HTTP请求,相应的响应时间也就会变的更快了。
您可以试一下下面的两个链接,自己体会一下Image maps所带来的速度上的不同。
No Image Map
http://stevesouders.com/hpws/imagemap-no.php
Image Map
http://stevesouders.com/hpws/imagemap.php
如果使用IE6在DSL(~900Kbps)的网络环境下,用image map的方法组成的导航栏要比用单独图片文件的所组成的导航栏要快56%(354ms 比 799ms).这是因为image map会减少四个HTTP请求。
Image Map最常用的实现方式是使用HTML的map标签,把大图片分成一个一个的小块,并设置其不同的链接。如下:
<img usemap="#map1" border=0 src="http://7career.org/images/imagemap.gif">
<map name="map1">
<area shape="rect" coords="0,0,31,31" href="http://7career.org/home.html" title="Home">
<area shape="rect" coords="36,0,66,31" href="http://7career.org/gifts.html" title="Gifts">
<area shape="rect" coords="71,0,101,31" href="http://7career.org/cart.html" title="Cart">
<area shape="rect" coords="106,0,136,31" href="http://7career.org/settings.html" title="Settings">
<area shape="rect" coords="141,0,171,31" href="http://7career.org/help.html" title="Help">
</map>
但是它所带来的缺点就是你得手动确定图片的坐标,这会比较乏味和容易出错,并且它只适合把图片都组合在一个长方形的区域里。
CSS Sprites (您可以参考YouTube和iGoogle的首页,它们就是采用的这种优化方式)
与image maps类似,CSS Sprites也是把若干小图片合成一个大图片,但是CSS Sprites方式更灵活。为了实现CSS Sprites,是把各个小图片像组成一个棋盘一样地合成一个图片。如下图: 然后通过HTML中任何能支持背景图片的元素,如<span>或<div>,再通过CSS中的background- position属性来定位要显示的大图片中的某个小图片的位置。如下,就是要在上面给出的在图片中使用"My"这个图标来充当下面这个div的背景:
<div style="background-image: url('a_lot_of_sprites.gif');
background-position: -260px -90px;
width: 26px; height: 24px;">
</div>
我把前面我介绍image map的例子转成CSS Sprites的形式:把导航栏的五个链接都放到一个名为navbar的DIV中。每个链接都有一个SPAN元素,在#navbar的样式中为SPAN元素定义了背景图片spritebg.gif,但每个SPAN都有一个不同的class以指明其具体显示的背景图片的偏移位置,正是利用了CSS中的 background-position属性。
<style>
#navbar span {
width:31px;
height:31px;
display:inline;
float:left;
background-image:url(/images/spritebg.gif);
}
.home { background-position:0 0; margin-right:4px; margin-left: 4px;}
.gifts { background-position:-32px 0; margin-right:4px;}
.cart { background-position:-64px 0; margin-right:4px;}
.settings { background-position:-96px 0; margin-right:4px;}
.help { background-position:-128px 0; margin-right:0px;}
</style>
<div id="navbar" style="background-color: #F4F5EB; border: 2px ridge #333;
width:180px; height: 32px; padding: 4px 0 4px 0;">
<a href="javascript:alert('Home')"><span class="home"></span></a>
<a href="javascript:alert('Gifts')"><span class="gifts"></span></a>
<a href="javascript:alert('Cart')"><span class="cart"></span></a>
<a href="javascript:alert('Settings')"><span class="settings"></span></a>
<a href="javascript:alert('Help')"><span class="help"></span></a>
</div>
这比image map的方式的例子要更快:342ms VS 354ms,但是他们之间的实现方式只有很小的不同。但重要的是,这可比用单独的五个图片的例子要快57%了。
CSS Sprites
http://stevesouders.com/hpws/sprites.php
我们看到,image map的方式要求所有的图片是连续的组合在一起的,而CSS Sprites没有这个限制。关于CSS Sprites的优缺点在Dave Shea的权威文章"CSS Sprites: Image Slicing's Kiss of Death"中已经有详细的介绍,但我已经从CSS Sprites中体会到它的优点:减少了HTTP请求,比image maps灵活。另一个让我没想到的优点是它减少了下载的数据量。大多数人可能会认为一个拼合成的大图片肯定要比这此小图片的总量要大,因为它会有一些小图片的间隔区域。实际上正相反,大图片减少了图片中的color tables和格式信息等,而使得大图片比一堆小图片实际size要小一些。
如果你的网站中有很多背景图片,按钮图片,导航栏图片,那么你应该用CSS Sprites方式来优化你的页面了。(您可以参考YouTube和iGoogle的首页,它们就是采用的这种优化方式)
Inline images(注:IE暂不支持,您可以跳过这一部分;但说不定什么时候IE就支持了)
我们上面所做的都是为了减少HTTP请求,现在有一个更绝的方式,把所有的图片都以base64编码以源代码的形式写在HTML源码里:data:[<mediatype>][;base64],<data> 所有对图片的HTTP请求,都化在了对HTML源文件的第一次请求里。
我们在HTML中肯定都用过ftp:,file:,mailto:这样的标签,实际上像这样的标签还有很多,只是我们平常不太使用,像:smtp:,pop:,dns:,whois:,finger:,daytime:,news:,urn:等等.
data:URL标签是在1995年第一次提出,按RFC2397规范的描述:它是"allows inclusion of small data items as 'immediate' data.(允许在页面中包含一些小的即时数据)"。如一个内嵌的小红星的图片可以这样引用:(在firefox下可以出来)
<IMG ALT="Red Star"
SRC="data:image/gif;base64,R0lGODlhDAAMALMLAPN8ffBiYvWW
lvrKy/FvcPewsO9VVfajo+w6O/zl5estLv/8/AAAAAAAAAAAAAAAACH5BAEA
AAsALAAAAAAMAAwAAAQzcElZyryTEHyTUgknHd9xGV+qKsYirKkwDYiKDBia
tt2H1KBLQRFIJAIKywRgmhwAIlEEADs=">
这样是挺方便吧,但它的不足之处也很明显:目前IE不支持;再就是FireFox1.5所能处理的line image有大小限制,不能超过100K;base64的编码会增加HTML的容量,总体下载量会增多。
Inline Images:http://stevesouders.com/hpws/inline-images.php
data:URL是内嵌在页面中的,所以它不会在页面之间缓存。所以您别用这种方法存储您公司的logo,因为它会增加您每个页面的容量。要解决这个问题,您可以把inline image写在CSS中,尽管date:URL不会被缓存,但CSS是可以被缓存的,Inline CSS Images:http://stevesouders.com/hpws/inline-css-images.php
下面就是接上面的例子,为每个SPAN加上inline image:
.home { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAAIxKA...);}
.gift { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAAABCp...);}
.cart { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAADlCr...);}
.settings { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAA...);}
.help { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAALW1t...);}
PHP的file_get_content函数可以很轻松的实现inline image的那串base64的图片编码。我上面的例子就是用的这个函数:
.home { background-image: url(data:image/gif;base64,
<?php echo base64_encode(file_get_contents("../images/home.gif")) ?>);}
.gift { background-image: url(data:image/gif;base64,
<?php echo base64_encode(file_get_contents("../images/gift.gif")) ?>);}
Combined Scripts and Stylesheets | 15
.cart { background-image: url(data:image/gif;base64,
<?php echo base64_encode(file_get_contents("../images/cart.gif")) ?>);}
.settings { background-image: url(data:image/gif;base64,
<?php echo base64_encode(file_get_contents("../images/settings.gif")) ?>);}
.help { background-image: url(data:image/gif;base64,
<?php echo base64_encode(file_get_contents("../images/help.gif")) ?>);}
我们比较一下上面的几个例子,image maps与CSS Sprites的响应时间基本上相同,但比使用各自独立图片的方式要快50%以上。用inline image与CSS组合的方式虽然增加一个HTTP请求,但是它可以以样式表的形式被缓存。
Combined Scripts and Stylesheets
尽量使用独立的js和样式表文件
现在的前端开发少不了JavaScript和CSS,但我们还是建议:使用外部的js和css文件引用的方式,因为这要比直接写在页面中性能要更好一点(细节会在Chapter 8中讨论)。但是如果你滥用这条规则,把你的代码切割成了很多个小文件,那只会增加更多的HTTP请求而影响性能。
表1-1是10大网站首页中js和样式表的数量表,它们的样式表都不多,但js显然还有优化的余地。
下面的例子中,你会发现用独立的一个js比用多个js文件组成的页面载入要快38%.
Separate Scripts
http://stevesouders.com/hpws/combo-none.php
Combined Scripts
http://stevesouders.com/hpws/combo.php
有的人可能会习惯于按功能或模块来把js分成各种不同的文件,但以我的经验,如果一个网站的页面引用大量的js文件,那应该要分析一下这些分类是否真的便于管理。
结论
这一章节介绍了我们在Yahoo!用到的以减少HTTP请求数量的技术方法。也是对访问网站很重要的一条法则。它会提高用户第一次访问您网站时的体验速度。而更快的访问速度将会使用户更愿意常回头访问您杰作。