先上一张从SegmentFault搬运来的缓存过程图
从图中能很清楚的看出来,缓存是怎样的一个运行流程,接下来我们将一一介绍几种缓存机制;
对于强制缓存来说,http头部中会有两个字段来标明失效规则(Expires/Cache-Control)
- Expires:
HTTP/1.0的缓存机制,Expires的值是服务器返回的过期时间,在过期之前浏览器都可以直接在缓存里读取相应的文件,但Expires存在一个BUG,这个BUG就是,Expires对比的时间是客户端的时间,也就是说,我们只要设置自己电脑的时间超过Expires的值就会被判定为相应的资源已经过期需要重新请求,所以可能会导致差错;优点是Expires的设置非常的简洁明了就是一个时间,示例:Expires: Thu, 01 Dec 1994 16:00:00 GMT
- Cache-Control:
Cache-Control是HTTP/1.1的产物,在request header与response header中都支持这个属性,值得注意的是,缓存指令是单向的, 这意味着在请求设置的指令,在响应中不一定包含相同的指令。
接下来来看一看Cache-Control的命令有哪些,作用都是什么:
- 请求指令与响应指令
缓存中不得存储任何关于客户端请求和服务端响应的内容。每次由客户端发起的请求都会下载完整的响应内容。 Cache-Control: no-storeCache-Control: no-cache, no-store, must-revalidate 缓存静态资源 Cache-Control:public, max-age=31536000 强制确认缓存
此方式下,每次有请求发出时,缓存会将此请求发到服务器(该请求应该会带有与本地缓存相关的验证字段),服务器端会验证请求中所描述的缓存是否过期,若未过期(返回304),则缓存才使用本地缓存副本。 Cache-Control: no-cache 协商缓存OR对比缓存
需要进行比较判断是否可以使用,浏览器第一次发送请求后,服务器返回一个缓存标识,在第二次请求的时候发送这个缓存标识,服务器对比,如果判断相同后返回304状态吗,浏览器就可以使用缓存数据了;在成功的情况下大家都只有http头部信息;
关于这里的缓存标识存在两种类型,就是
在服务器返回相应资源的时候在头部信息当中带上Last-Modified属性告诉浏览器,这个资源最后的修改时间,浏览器再次请求的时候会发送头部信息带上If-Modified-Since属性值为上一次服务器给出的Last-Modified,服务器进行匹配,匹配成功则说明资源没有更改返回304状态码,如果发现资源的修改时间大于If-Modified-Since则说明资源被改动过了,那么就会返回完整的资源和200状态码,并在头部信息中返回Last-Modified属性,浏览器也会更新相应的资源状态,在下次的If-Modified-Since中使用上一次服务器返回的Last-Modified值;
Etag/If-None-Match:Etag是实体标签(Entity Tag)的缩写,是服务器资源的唯一标识符。在资源的各个生命周期中,它都具有不同的值,用于标识出资源的状态。当资源发生变更时,如果其头信息中一个或者多个发生变化,或者消息实体发生变化,那么ETag也随之发生变化。大概的服务器与浏览器的Etag/If-None-Match与Last-Modified/If-Modified-Since相同。
需要注意的点是:
1. Etag/If-None-Match的优先级高于Last-Modified/If-Modified-Since
2. 如果内容发生了变化,使用ETag有助于防止资源的同时更新相互覆盖(空中碰撞)
3. Last-Modified 标注的最后修改时间只能精确到秒,如果有些资源在一秒之内被多次修改的话,他就不能准确标注文件的新鲜度而Etag能做到
4. 语法,强弱校验器
‘W/’(大小写敏感) :表示使用弱验证器。 弱验证器很容易生成,但不利于比较。 强验证器是比较的理想选择,但很难有效地生成。 相同资源的两个弱Etag值可能语义等同,但不是每个字节都相同。
etag_value:实体标签唯一地表示所请求的资源。 它们是位于双引号之间的ASCII字符串(如“675af34563dc-tr34”)
5.Etag并没有规范的生成方式,ETag值可以是唯一标识资源的任何东西,如持久化存储中的某个资源关联的版本、一个或者多个文件属性,实体头信息和校验值,也可以计算实体信息的散列值。有时候计算Etag的代价很大(哈希算法),有时候代价很小,所以就需要考虑在代价很大的时候通常将计算出的值保存下来,而在计算代价小的时候则通过每次去重新计算。
SO,很明显在协商缓存中,Etag的代价比Last-Modified/If-Modified-Since大,但是更精确,Etag的应用范围也更广,在项目中根据情景去使用了;
另外关于强缓存与协商缓存应该是并存公用的,浏览器会先检查强缓存,当强缓存命中的时候就会直接去加载资源,没有命中的情况下会进行协商缓存;
最后在缓存当中,我们应该去缓存那些静态资源和不经常改变的资源,例如:Logo和商标图像、普通的不变化的图像、CSS样式表、普通的Javascript文件、可下载的内容、媒体文件等,千万不要去缓存经常变化的内容和用户的敏感信息(虽然缓存通常对于跨域页面是不可以共享的)
OK,如果有什么地方不对和补充,就评论吧(●’◡’●)