浏览器的资源请求,若是使用了缓存基本上是两种状况css
上面两种方式有什么区别呢?简单地说,第一种方式是不向浏览器发送请求,直接使用本地缓存文件。第二种方式,浏览器虽然发现了本地有该资源的缓存,可是不肯定是不是最新的,因而想服务器询问,若服务器认为浏览器的缓存版本还可用,那么便会返回304。html
那么,浏览器如何决定是使用哪一种方式呢?这就和服务器在请求返回中的Header字段有关了。下面对相关的字段进行简单介绍。node
Cache-Control 是最重要的规则。这个字段用于指定全部缓存机制在整个请求/响应链中必须服从的指令。该字段一般覆盖默认缓存算法。另外,缓存指令是单向的,即请求中存在一个指令并不意味着响应中将存在同一个指令。git
简单地说,该字段用于控制浏览器在什么状况下直接使用本地缓存而不向服务器发送请求。通常具备如下值:github
public
: 全部内容都将被缓存private
: 内容只缓存到似有缓存中no-cache
: 全部内容都不会被缓存no-store
: 全部内容都不会被缓存到缓存或者internet临时文件中must-revalidation/proxy-revalidation
: 若是缓存的内容失效,请求必须发送到服务器/代理以进行从新验证max-age=xxx( xxx is numeric )
: 缓存的内容将在 xxx 秒后失效, 这个选项只在HTTP 1.1可用, 并若是和Last-Modified一块儿使用时, 优先级较高其中最经常使用的属性即是 max-age
, 这个字段很简单,就是浏览器在资源成功请求后的制定时间内,都将直接调用本地缓存和不会向服务器去请求数据。算法
Expires 头部字段提供一个日期和时间,在该日期前的全部对该资源的请求都会直接使用浏览器缓存而不用向服务器请求(注意:cache-control max-age 和 s-maxage 将覆盖 Expires 头部。)apache
Expires 字段接收如下格式的值:“Expires: Sun, 08 Nov 2009 03:37:26 GMT”。浏览器
可是使用Expires
存在服务器端时间和浏览器时间不一致的问题。缓存
Last-Modified
和E-tag
的做用都是向服务器确认当前缓存文件是否为最新。抛开功能不看,这两个字段的表现以下:服务器
Last-Modified
字段,那么当下一次浏览器再一次向服务器请求该资源时(前提是浏览器中上一次的资源被缓存过了),会在请求header中包含If-Modified-Since
字段,且值与服务器第一次响应给浏览器的Last-Modified
字段一致ETag
字段,那么当下一次浏览器再一次向服务器请求该资源时(前提是浏览器中上一次的资源被缓存过了),会在请求header中包含If-None-Match
字段,且值与服务器第一次响应给浏览器的ETag
字段一致那么上述是遵循了Http协议的浏览器会自动实现的,而要实现304的功能,就须要服务器(好比Apache对于静态资源会自动实现这两个字段的响应)或者咱们手动在服务器端编写响应的逻辑来实现。
Last-Modified
字段,则说明浏览器中包含了该资源的某一版本的缓存,此时服务器端将根据该字段的值进行必定的逻辑判断,以决定让浏览器直接使用已有的缓存(返回304
)仍是将最新的文件发送过去(200
,发送新文件并更新Last-Modified
字段)If-None-Matc
字段,则说明浏览器中包含了该资源的某一版本的缓存,此时服务器端将根据该字段的值进行必定的逻辑判断,以决定让浏览器直接使用已有的缓存(返回304
)仍是将最新的文件发送过去(200
,发送新文件,并更新ETag
)若同时使用了Last-Modified
和ETag
,正确的作法应该是当二者都符合条件时,才返回304
Etag
主要为了解决 Last-Modified
没法解决的一些问题。
md5
)来做为ETag
If-Modified-Since
能检查到的粒度是s级的,这种修改没法判断(或者说UNIX记录MTIME只能精确到秒)通常咱们打开(或者更新)一个页面(或者资源)有几种方式:
上面几种方式对资源的请求,会产生不一样的结果,而且各浏览器的表现并不一致。具体的区别能够参考鸟哥的《浏览器缓存机制》
其中你们须要注意的一点是,刷新页面(F5或者刷新按钮),不论是否设置了max-age
,都会从新像服务器发送请求。可是这不影响304
逻辑。
用nodejs
写了一个简单的静态文件服务器,用来测试上面的Cache-Control
和Last-Modified
,具体代码能够看gist
例子比较简单,大致逻辑:
200
返回设置max-age=10
,即缓存10秒。同时设置Last-Modified
if-modified-since
字段,则304
测试过程和结果:
index.html
仍是index.css
均为200
,且response中包含了max-age
和Last-Modified
index.html
为304
,index.css
为200 ok ( from cache )
304
(在10s内或者不在10s内)须要注意的问题:
index.html
不论是否设置了max-age
,都是304
,同理,将index.css
直接放到地址栏中请求也是304
index.css
一次304
以后的10s内又能继续进行不须要请求服务器的直接本地缓存。这里我我的认为,浏览器的“直接使用本地缓存“的效果和从服务器成功200
到数据产生的效果是一致的,除了文件自己,header字段等信息也是一样会被cache的,所以304
以后,max-age
又能够被继续使用一遍。作了nodejs
的实验以后,又开启了apache
服务器,一样的将index.html
和index.css
文件放置到服务器根目录中,请求后,发现apache
默认已经作了Last-Modified
和ETag
的处理,而且在修改index.css
文件后,能够观察到这两个值的变化。