欢迎探讨,有不对之处,还望指正。
HTTP有客户端(浏览器)发起请求、服务器端发送响应,因此,缓存也要从两方面谈起。
服务器端可以要求浏览器缓存还是不缓存,以及告诉一些缓存的额外信息。
浏览器可以听服务器端的缓存要求,也可以强制不听你丫的。
通常来说,缓存控制的主要部分由服务器端控制,毕竟浏览的内容是从服务器端出来的,服务器端清楚这份内容是否能缓存以及各种各要的额外信息。
一、服务器端(使用PHP验证):
1、Cache-Controll首部(Cache-Control: XXX)。
Cache-Controll大致分为:no-store、no-cache(must-revalidate)、max-age。
no-store:hey,浏览器,这个内容不要缓存了,别嫌麻烦,每次都来拿吧。
no-cache:hey,浏览器,这个内容你可以缓存,但是下次用的时候要到我这里验证一下有没有失效,别你妹的拿出来就用。
(注:Cache-Control: no-cache跟Pragma: no-cache是一回事,Pragma是HTTP/1.0里面的首部,1.1里应该用Cache-Control: no-cache)
max-age:hey,浏览器,这个内容从现在开始多少s之后就要过保质期了,下次用的时候悠着点,看看有没有过这个有效期。
(注:
A、Cache-Controll: max-age=0效果等同于Cache-Controll: no-cache
B、max-age的控制方式等同于Expires首部(如Expires: Sat, 02 Feb 2013 12:43:44 GMT),只是Expires是绝对时间控制过期,max-age是相对时间控制,由于服务器跟客户端时间可能有偏差,推荐使用max-age。
)
2、Last_Modified首部(Last_Modified: timestring)。
表示这个内容上一次更改时间。具体有啥用,一会讲浏览器端再讲。
3、ETag首部(Etag: tag)。
表示这个内容的版本号,标签。
上述的这些标签,有的可以并行,有的也有冲突,大家自己根据实际情况组合使用。
二、客户端(浏览器端):
我这边用的chrome验证的,可能不同浏览器不一致。
再服务器端用上述的几个标签告诉浏览器缓存的信息时,浏览器端的正常反应如下(浏览器缓存开启的情况下):
A、no-store:内容返回后,就不存缓存了,每次都去老老实实取
B、no-cache:内容返回后,存缓存,如果有Last_Modified,下次获取内容时会加一个请求首部If_Modified_since: xxx。如果有ETag,下次获取内容时会加一个请求首部If-None-Match: xxx。这样有If打头首部的GET请求,都称为条件GET。
If-None-Match: "V1.0"
If-Modified-Since: Sunday, 24-Mar-13 11:06:00 CST
服务器端如果检测到这两个首部,就应该先去核实下最新内容的修改日期或者版本号,如果没有不同,直接返回304 Not Modified状态码,不再返回详细内容了,否则按照正常获取流程,返回具体内容。
C、max-age大于0以及Expires首部大于当前时间:内容返回后,缓存,同时下次获取内容时,如果没有过期,就不去取数据了,直接从缓存里拿。
浏览器没获取一个资源前大致流程如下:
1、找缓存。如果有,拉出来看看;没有,直接去http请求。
2、如果缓存通过上述C的方式判断出来看看过期没。还没过期,直接用。(可以通过no-cache、must-revalidate跳过此步)
3、如果不确定有没有过期,用上述B的方式尝试条件GET;组合不出IF_首部的话,直接GET。
4、服务器返回304,用缓存,否则用服务器返回的新内容。
三、以下是一些代码验证
1、
header("Cache-Control: no-store");
header("ETag: \"V1.0\"");
header("Last-Modified: " . date(DATE_RFC850));
虽然设置了ETag等,但是每次请求都不会带上If_XXX,因为压根就不缓存
2、
header("Cache-Control: no-cache");
header("ETag: \"V1.0\"");
header("Last-Modified: " . date(DATE_RFC850));
发请求时会带上If条件首部。
3、
header("Cache-Control: max-age=3600");
header("Expires: " . date(DATE_RFC850, time()+3600));
直接用缓存了
另注:有的资料上说可以在html中加入meta标签HTTP-EQUIV的方式控制缓存,强烈推荐不要使用,一方面会加重web服务器生成这些额外meta的压力,另一方客户端解析header与解析内容哪个效率高,不言而喻,很多浏览器都不支持这种meta。