参阅了一些浏览器缓存的资料,本文经过一张图来概括总结其过程。html
浏览器第一次向一个web服务器发起http
请求后,服务器会返回请求的资源,而且在响应头中添加一些有关缓存的字段如:Cache-Control
、Expires
、Last-Modified
、ETag
、Date
等等。以后浏览器再向该服务器请求该资源就能够视状况使用强缓存和协商缓存。web
下面假定浏览器已经访问了服务器,服务器返回了缓存相关的头部字段且浏览器已对相关资源作好缓存。经过下图来分析强缓存和协商缓存:浏览器
如图红线所示的过程表明强缓存。用户发起了一个http
请求后,浏览器发现先本地已有所请求资源的缓存,便开始检查缓存是否过时。有两个http头部字段控制缓存的有效期:Expires
和Cache-Control
,浏览器是根据如下两步来断定缓存是否过时的:缓存
Cache-Control
的s-maxage
或max-age
指令,如有,则使用响应报文生成时间Date + s-maxage/max-age
得到过时时间,再与当前时间进行对比(s-maxage
适用于多用户使用的公共缓存服务器);Cache-Control
的s-maxage
或max-age
指令,则比较Expires
中的过时时间与当前时间。Expires
是一个绝对时间。注意,在HTTP/1.1中,当首部字段Cache-Control
有指定s-maxage
或max-age
指令,比起首部字段Expires
,会优先处理s-maxage
或max-age
。服务器
另外下面列几个Cache-Control
的经常使用指令:spa
no-cache
:含义是不使用本地缓存,须要使用协商缓存,也就是先与服务器确认缓存是否可用。no-store
:禁用缓存。public
:代表其余用户也可以使用缓存,适用于公共缓存服务器的状况。private
:代表只有特定用户才能使用缓存,适用于公共缓存服务器的状况。通过上述两步判断后,若缓存未过时,返回状态码为200
,则直接从本地读取缓存,这就完成了整个强缓存过程;若是缓存过时,则进入协商缓存或服务器返回新资源过程。code
当浏览器发现缓存过时后,缓存并不必定不能使用了,由于服务器端的资源可能仍然没有改变,因此须要与服务器协商,让服务器判断本地缓存是否还能使用。此时浏览器会判断缓存中是否有ETag
或Last-Modified
字段,若是没有,则发起一个http请求,服务器根据请求返回资源;若是有这两个字段,则在请求头中添加If-None-Match
字段(有ETag
字段的话添加)、If-Modified-Since
字段(有Last-Modified
字段的话添加)。注意:若是同时发送If-None-Match
、If-Modified-Since
字段,服务器只要比较If-None-Match
和ETag
的内容是否一致便可;若是内容一致,服务器认为缓存仍然可用,则返回状态码304
,浏览器直接读取本地缓存,这就完成了协商缓存的过程,也就是图中的蓝线;若是内容不一致,则视状况返回其余状态码,并返回所请求资源。下面详细解释下这个过程:htm
ETag
和If-None-Match
两者的值都是服务器为每份资源分配的惟一标识字符串。blog
ETag
字段。资源更新时,服务器端的ETag
值也随之更新;If-None-Match
字段,它的值就是上次响应报文中的ETag
的值;ETag
与If-None-Match
的值是否一致,若是不一致,服务器则接受请求,返回更新后的资源;若是一致,代表资源未更新,则返回状态码为304
的响应,可继续使用本地缓存,要注意的是,此时响应头会加上ETag
字段,即便它没有变化。Last-Modified
和If-Modified-Since
两者的值都是GMT格式的时间字符串。ip
Last-Modified
字段,代表该资源最后一次的修改时间;If-Modified-Since
字段,它的值就是上次服务器响应报文中的Last-Modified
的值;Last-Modified
与If-Modified-Since
的值是否一致,若是不一致,服务器则接受请求,返回更新后的资源;若是一致,代表资源未更新,则返回状态码为304
的响应,可继续使用本地缓存,与ETag
不一样的是:此时响应头中不会再添加Last-Modified
字段。ETag
较之Last-Modified
的优点如下内容引用于:http协商缓存VS强缓存
你可能会以为使用Last-Modified
已经足以让浏览器知道本地的缓存副本是否足够新,为何还须要ETag
呢?HTTP1.1
中ETag
的出现主要是为了解决几个Last-Modified
比较难解决的问题:
GET
;If-Modified-Since
能检查到的粒度是s级的,这种修改没法判断(或者说UNIX
记录MTIME
只能精确到秒);这时,利用ETag
可以更加准确的控制缓存,由于ETag
是服务器自动生成的资源在服务器端的惟一标识符,资源每次变更,都会生成新的ETag
值。Last-Modified
与ETag
是能够一块儿使用的,但服务器会优先验证ETag
。
最后附一张图说明用户行为对浏览器缓存的影响: