http缓存是我们常用的优化手段之一,在http发展的不同阶段缓存机制也越来越完善,这里我们较为完整的总结一下。
http1.0阶段
1. Pragma
主要值为no-cache 与http1.1中的cache-control:no-cache一致,表示不缓存 。为了兼容http1.0.在http1.1中也可以用。
2. Expire
Expires 的值对应一个 GMT (格林尼治时间),比如 “Mon, 22 Mar 2017 11:12:01 GMT” 来告诉浏览器资源缓存过期时间,如果还没有超过该时间点则不发请求,直接返回 200 OK。(from cache)。
3. 额外注意
Pragma的优先级高于expire,expire的时间是相对于服务器,而浏览器判断是否过期是相对于客户端的时间。所以会有问题。
max-age是相对于请求时间设置的一个有效时间长度,Expire可以相对于上次访问时间也可以相对于文件的修改时间,max-age优先。注意: 在有效时间内不会发出请求,fromcache
http1.1
1. cache-control
比如: Cache-Control: max-age=3600, must-revalidate;
它意味着该资源从原服务器上取得的,且其缓存的有效时间为一小时,在后续一小时内,用户重新访问该资源则无需发送新的请求。
Cache-Control: no-cache, no-store;
它告诉浏览器不使用缓存,要求每次请求要向服务器发送请求,并且所有内容都不会被保存到缓存或者临时文件中。
因此cache-control:no-cache不是不缓存。这点与pragma不同。当然组合方式也有一定的限制,比如 no-cache 不能和 max-age 一起搭配使用。
2. Last-Modified
提升缓存的使用率,设置的过期时间到了,但是服务端的资源不一定有修改,这个时候缓存依然有效。
此时服务端会返回last-modified字段
客户端发送这个内容:
If-Modified-Since: Last-Modified-value;该字段告诉服务器如果客户端传来的最后修改时间和服务器上的一致,直接返回 304 状态码即可,当前各大浏览器均是使用该字段来向服务器传递保存的 Last-Modified 的值。
(1) 如果真的被修改:那么就开始传输,服务器返回:200 OK
(2) 如果没有被修改:那么就无需传输,服务器返回:304 Not Modified.
If-Unmodified-Since: Last-Modified-value;该字段告诉服务器如果客户端传来的最后修改时间和服务器上的不一致,则直接返回 412 状态码(Precondition Failed)。
(1) 如果没有被修改:则开始继续传送文件,服务器返回: 200 OK
(2)如果文件被修改:则不传输,服务器返回:412 Precondition failed (预处理错误)。比如断点续传就会使用到这个字段(一般会指定 Range 参数),要想断点续传,那么文件就一定不能被修改,否则就不是同一个文件。缺陷:如果文件被修改了,但是其实内容并没有变化,这个时候就不准确了
3. Etag
服务端会返回Etag字段,表示文件的唯一标示
客户端请求带上这个标示:
- If-None-Match: "qwerrgerg-1332"
告诉服务端如果 ETag 没匹配上需要重发资源数据,否则直接回送304 和响应报头即可。 - If-Match: ETag-value
该字段告诉服务器如果客户端传来的 Etag 值跟服务器上的不一致,则直接返回 412 状态码(Precondition Failed)。
4.其他
混合使用: Last-Modified 和 ETag往往是同时被使用,则要求它们的验证都必须通过才会返回304,若其中某个验证没通过,则服务器会按常规返回资源实体及200状态码。
总结
总的来说其实是两个阶段,一个是直接缓存,这个时候不会发起请求,直接从本地获取,而缓存过期就要发起请求了,当请求的文件没有变化的时候,浏览器再从缓存中获取,此时就会有304了,所以说,不是所有的http缓存都有304。