高性能网站建设
Tracking Web Page Performance 跟踪网站性能
HTTP Overview HTTP概览
当使用GET
方法下载脚本yahoo_2.0.0-b2.js
的时候,发送的可能的HTTP headers
:
Compression 压缩
Conditional GET Requests 有条件性的GET请求
如果浏览器有一份拷贝,但是它不确定是否可以使用,那么一个conditional GET request
将会被请求;如果缓存的拷贝可以使用,那么会响应变快。一般来说,缓存的拷贝的日期是从last modified
开始计算的。浏览器根据Last-Modified
头可以计算出这个资源是什么时候被更改的,然后它再使用If-Modified-Since
头发送至服务器,告诉服务器:“我有一份这个时候的资源,我可以重用它吗?”
如果资源没有被更改过,那么服务器将会返回304 Not Modified
状态码,不会发送该资源的body
,也会加速响应。在HTTP/1.1
中,ETag
和If-None-Match
这两个头是另外一种make conditional GET requests
的方式。
Expires 截止日期
Conditional GET requests
和304
虽然能够有效的帮助页面加载变快,但是它还是在客户端和服务器端发送了一轮请求。使用Expires
可以取消这种有效性检查,让浏览器直接决定是否可以使用这份拷贝。当浏览器看到Expires
头之后,它会保存起来,在这个期间,它不会发送任何请求。
Keep-Alive 保持存活
Persistent Connections
(also known as Keep-Alive
in HTTP/1.0) 就是用来解决经常在一个服务器上不停打开和关闭多个socket connections
低效的问题的。它让浏览器在一条连接connection
中发送多个请求。
当然浏览器或者服务器也可以主动关闭连接,通过在头里面加入字段Connection: close
。Pipelining
,是在HTTP/1.1
中引入的,它允许在一个socket
上发送多个请求而不需要等待其响应。
Rule 1: Make Fewer HTTP Requests 更少的HTTP请求
Image Maps 图片地图
<img usemap="#map1" border=0 src="/images/imagemap.gif">
<map name="map1">
<area shape="rect" coords="0,0,31,31" href="home.html" title="Home">
<area shape="rect" coords="36,0,66,31" href="gifts.html" title="Gifts">
<area shape="rect" coords="71,0,101,31" href="cart.html" title="Cart">
<area shape="rect" coords="106,0,136,31" href="settings.html" title="Settings">
<area shape="rect" coords="141,0,171,31" href="help.html" title="Help">
</map>
CSS Sprites CSS精灵
#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;
}
Inline Images 内联图片
data: [<mediatype>][;base64],<data>
例如:
<IMG ALT="Red Star" src="data:image/gif;base64,R0lGODlhDAAMALMLAPN8ffBiYvWWlvrKy/FvcPewsO9VVfajo+w6O/zl5estLv/8/AAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAMAAwAAAQzcElZyryTEHyTUgknHd9xGV+qKsYirKkwDYiKDBiatt2H1KBLQRFIJAIKywRgmhwAIlEEADs=">
Combined Scripts and Stylesheets 合并脚本和CSS样式文件
Rule 2: Use a Content Delivery Network 使用CDN
Rule 3: Add an Expires Header 添加截止日期头
Expires Header 截止日期
Max-Age and mod_expires
HTTP/1.1
引入了Cache-Control
,目的是为了突破Expires
的一些限制,因为Expires
头使用一个精确的日期,因此需要服务器和客户端保持精确的时间同步。因此Cache-Control
使用max-age
来指定缓存多长时间(使用秒),尽管引入了这一机制,但是你还是应该尽量提供Expires
,因为有些浏览器可能不支持。
Empty Cache vs. Primed Cache
More Than Just Images 不仅仅是图片
脚本、CSS文件、Flash组件等等都可以缓存
Revving Filenames
当我们在缓存的这段时间,如果修改了图片,那么应该怎么办呢?最好的方法就是修改文件的名字
Rule 4: Gzip Components Gzip 组件
What to Compress 应该压缩什么
压缩HTML文档、XML、JSON、Scripts、Stylesheets,不用压缩图片和PDF,因为它们本来就已经被压缩过了。压缩需要更多的CPU,一般来说当文件大于1~2K的时候是值得压缩的
Proxy Caching 代理缓存
Web服务器根据Accept-Encoding
来决定是否压缩,但当通过一个代理服务器来发送的时候,情况开始变得复杂了。假设发往代理服务器的请求不支持gzip
,代理服务器转发请求给服务器,之后服务器响应结果返回,代理服务器缓存了一份。现在假设第二个请求支持gzip
,代理服务器便会把自己缓存的一份发给客户端,这样便会失去gzip
的使用。如果这两种情况反过来,情况就更加糟糕了。解决这种情况的方法就是让你的服务器添加头字段Vary:Accept-Encoding
,这样的话,代理服务器就会缓存多个版本的文件。
Edge Cases
Rule 5: Put Stylesheets at the Top 把样式文件放在最上面
CSS at the Top CSS放在顶部
CSS放在顶部主要是为了防止出现白屏
Put your stylesheets in the document
HEAD
using theLINK
tag.
Rule 6: Put Scripts at the Bottom 脚本放在底部
Parallel Downloads 并行下载
Scripts Block Downloads 当脚本下载的时候浏览器不会去下载其它任何东西
Move scripts to the bottom of the page.
Rule 7: Avoid CSS Expressions 避免CSS表达式
Updating Expressions
CSS表达式计算的频率比大多数人预料的要多很多,当页面渲染、尺寸变化、滑动鼠标、移动鼠标许多情况下都会计算
Avoid CSS expressions.
Rule 8: Make JavaScript and CSS External 把JavaScript和CSS文件放在外面
Put your JavaScript and CSS in external files
Rule 9: Reduce DNS Lookups 减少DNS查询
Reduce DNS lookups by using Keep-Alive and fewer domains
Rule 10: Minify JavaScript 压缩JavaScript
Minify your JavaScript source code.
Rule 11: Avoid Redirects 避免重定向
304 Not Modified
不是一个真正的重定向,它用在conditional GET requests来避免下载已经在浏览器里缓存的文件301 Moved Permanently
Find ways to avoid redirects.
Rule 12: Remove Duplicate Scripts 移除重复的脚本
Make sure scrips are included only once
Rule 13: Configure ETags 配置ETags
ETags是Entity tags的缩写,它是服务器和浏览器用来验证缓存组件有效性的一种机制。目前有两种方式可以比较自己缓存的组件和服务器端的究竟是否一致:
- 比较
last-modified
日期 - 比较
entity tag
组件的last-modified
日期是通过服务器返回的:
之后,浏览器便会缓存起来这个组件,然后等下一次请求的时候,浏览器便会把last-modified
的这个日期设置进If-Modified-Since
里面,如果没有变的话,304 Not Modified
便会返回。
Entity Tags
Entity Tags
是另外一种比较资源是否有效的机制。服务器把资源的ETag
值设置进ETag
头里面。
随后,当浏览器想要检查资源是否有效的时候,它会使用If-None-Match
头来把之前缓存的ETag
值重新传递给服务器,如果匹配,那么304 Not Modified
将会返回。
The Problem with ETags Etags的问题
- 相同的组件从不同的服务器下载,
Etag
不一致
Reconfigure or remove ETags
Rule 14: Make Ajax Cacheable 使Ajax可缓存
Make sure your Ajax requests follow the perfomance guidelines, especially having a far future Expires header.