如何正确设置缓存

web页面变得越来越胖,这意味着更多脚本、样式、图片和flash。初次访问站点的访客不得不请求很多HTTP请求,但是可以通过设置 Expire头来让这些文件缓存起来,避免重复的HTTP请求。Expire头经常用在图片上,但在脚本、样式和flash上都应使用这一技术。

Expire

Expire头的设置在服务器端进行,服务请求通过在HTTP相应中增加Expire头来告诉客户端该文件可以缓存多久,比如:

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

告诉浏览器,该文件在2020年之前都不会过期。

比如33号铺的样式返回的Expires:

所以浏览器再次访问这个资源的时候,可能是输入地址访问,我们可以看到:

如果我F5,会看到下图(304下面解释)

最好如果我Ctrl+F5,就会看到下图:

如果你的服务器是Apache,可以通过ExpiresDefault来配置一个相对现在日期的时间段。比如:

ExpiresDefault "access plus 10 years"

时刻记住,如果你使用了超长缓存,那么希望变更文件的时候就必须使用另一个文件名了。在Qzone我们使用时间戳来实现修改文件名的效果:

http://qzonestyle.gtimg.cn/qzone_v6/icenter.css?max_age=31536000&d=2012524161750

这个url中?后面的字符只要跟客户端缓存中的字符不匹配,客户端就会认为是新的图片。值得说明的是,Qzone使用HTTP 304而不是Expire来实现缓存控制。

HTTP 304(Cache-control)

304 的标准解释是:Not Modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。

如果客户端在请求一个文件的时候,发现自己缓存的文件有 Last Modified ,那么在请求中会包含 If Modified Since ,这个时间就是缓存文件的 Last Modified 。因此,如果请求中包含 If Modified Since,就说明已经有缓存在客户端。只要判断这个时间和当前请求的文件的修改时间就可以确定是返回 304 还是 200 。对于静态文件,例如:CSS、图片,服务器会自动完成 Last Modified 和 If Modified Since 的比较,完成缓存或者更新。但是对于动态页面,就是动态产生的页面,往往没有包含 Last Modified 信息,这样浏览器、网关等都不会做缓存,也就是在每次请求的时候都完成一个 200 的请求。

所以第一次请求:

对于第二次请求:

注意看清楚Request和Response的区别。

跟Expire一样的是:

第一次访问 200
鼠标点击二次访问 (Cache)
按F5刷新 304
按Ctrl+F5强制刷新 200

Expires vs Cache-control

200(缓存)是最快的,因为没有请求发生。304则产生了HTTP请求:浏览器发送一个带有If-Modified-Since的请求,服务器根据情况返回304来告诉浏览器使用本地文件。

所以304比200(缓存)慢一点,静态文件都应该使用Expires头来减少请求,提高访问速度。(根据HTTPWATCH的说法:“Don’t cache HTML, Cache everything else forever”)

如果服务器又设置了Cache-Control:max-age和Expires呢,怎么办?

答案是同时使用,也就是说在完全匹配If-Modified-Since和If-None-Match即检查完修改时间和Etag之后,服务器才能返回304.(不要陷入到底使用谁的问题怪圈)

参考资料:http://blog.httpwatch.com/2007/12/10/two-simple-rules-for-http-caching/

http://developer.yahoo.com/performance/rules.html#expires

http://www.ardamis.com/2010/07/17/sending-headers-to-leverage-browser-caching/

http://stackoverflow.com/questions/535053/which-webbrowsers-use-http-1-1-by-default

 

PS:以上基本上对静态文件有效,动态文件只在url+回车有效

<?php
$interval = 60 * 60 * 24;
$max = time()+$interval;
header ("Last-Modified: " . gmdate ('r', $max));
header ("Expires: " . gmdate ("r", $max));
header ("Cache-Control: max-age=$interval");
echo time();

关于F5 ctrl+F5 url+回车的区别见相关文章

posted on 2012-08-15 18:57  kudosharry  阅读(585)  评论(0编辑  收藏  举报

导航