浏览器的缓存机制:
- 1: 浏览器会在第一次请求完服务器后得到响应, 我们可以在服务器中设置这些相应,
从而达到在以后的请求中尽量减少甚至不从服务器获取资源的目的。 -
2: 浏览器缓存中涉及到的头信息
浏览器的缓存是依靠请求和响应中的的头信息来控制缓存的。1: expires
最简单的过期缓存方式, 在第一次请求时返回的头信息中设置一个exires时间,在后面的请求的时候, 请求会带着这个expires时间, 假如在这个expires时间内,浏览器不会向服务器发送请求, 而是直接从本地缓存副本中读取数据2:Cache-Control
他有一些不同的值对应不同的缓存策略,这里我查到一个,参考一下初探 HTTP 1.1 Cache 機制
这里要说明的是Cache-Control的设置会覆盖expires的设置, 而且常与Last-Modified和Etag配合使用3:Last-Modified/Last-Modified-Since
在使用这个缓存策略的时候, 浏览器每次都会向服务器发送请求, 但服务器可以根据Last-Modified-Since向浏览器返回200或者304, 如果返回304, 就是告诉浏览器让它直接从客户端电脑的缓存中读取副本吧, 否则就会把请求的资源以200的方式返回给浏览器。这里也要说明一下, Last-Modified是浏览器第一次向服务器请求之后, 服务器响应中设置的(即代码中设定), 而Last-Modified-Since则是浏览器每次向服务器请求的时候带着的Last-Modified的值, 比如第一次请求后响应的Last-Modified的值是A, 那么在后面每次请求的时候的Last-Modified-Since的值就是A, 直到服务器重新设置了Last-Modified的值
4: Etag/If-None-Match
ETag是一种与Last-Modified/Last-Modified-Since类似的控制方式。用户在第一次请求的时候服务器可以自己生成或由用户生成, 然后响应给浏览器, 那么在以后的请求中,会带着If-None-Match, 它的值就是之前生成的Etag。 在服务器中对比服务器上的Etag与If-None-Match, 假如相同, 则返回304, 否则请求并返回服务器资源。这里有一个问题, 如何生成Etag, 尤其是动态页面中, 假如资源发生变化, Etag要重新生成。 我这里想到一种方式, 请求到服务器后, 还是要进行必要的代码运行, 在代码中, 拿到相关的变量生成一个Etag值, 对比传递上来的If-None-Match, 再判定返回的状态值。(原谅我的经验有限, 这只是一种方式,如果各位有新的思路, 欢迎加入讨论)。
5: Cache-Control/Expires的优先级要高于Last-Modified/Etag,Cache-Control/Expires是控制浏览器是否向服务器拉资源, Last-Modified/Etag是服务器控制是否返回一个完整的请求资源,还是返回一个304, 假如本地连请求都不会拉, 那Last-Modified/Etag就无从谈起了.
实现:
下面使用PHP分别实现以上几种缓存方式, 一般服务器上的静态文件都会默认使用Last-Modified/Last-Modified-Since,
所以很多的静态文件在二,三,四。。。次刷新的时候都是304状态(Not Modified).
另外下面的过期时间都是格林威治时间才行,可以使用gmdate函数获取。
/*
Last-Modified/Last-Modified-Since
我想这里如果用一些数据保存方式,如memcache或数据库, 把某个文件的修改时间保存起来, 如果文件修改了, 则更新这个数据, 然后每次刷新这里的这个页面的时候,先读取修改时间, 如果传递的$lastModifiedSince修改时间不符, 则重新读取, 否则返回304
测试的结果是在在缓存时间内返回304
*/
$cacheTime = 60;
$lastModifiedSince = strtotime(@$_SERVER['HTTP_IF_MODIFIED_SINCE']);
if($lastModifiedSince + $cacheTime > time())
{
header("HTTP/1.1 304");
die('use cache');
}
header('Last-Modified: '.gmdate('D d M Y H:i:s', time()).' GMT');
echo time();
/*
Etag/If-None-Match
测试的结果是在服务器上的资源未发生变化时返回的304
*/
$user_id = 1;
$etag = md5($user_id);
$matchEtag = @$_SERVER['HTTP_IF_NONE_MATCH'];
if($matchEtag == $etag)
{
header("HTTP/1.1 304");
die('use cache');
}
header('Etag: '.$etag);
echo time();
问题:
在测试expires和Cache-Control的max-age的时候, 本地缓存无效, 每次还是发起请求, 并没有读取缓存, 不知为何?
请看连接
PS: 文章中可能有错误的地方, 如果发现, 请及时指出
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。