浏览器缓存
接下来以三个部分来学习一下浏览器的缓存机制:
- 强缓存
- 协商缓存
- 缓存的位置
1、强缓存
强缓存不需要发送
HTTP请求。是否强缓存由
Expires、Cache-Control和Pragma3 个Header属性共同来控制。
HTTP/1.0时期,是否强缓存使用的是Expires,而HTTP/1.1使用的是Cache-Control。让我们首先来看看Expires。
Expires
Expires即过期时间,存在于服务器返回的响应头中,其用于告诉浏览器在某个时间之前可以直接从缓存里面获取数据,不需要再次向服务器发送请求。Expires的优先级在三个Header属性中是最低的。
缺点
用 Expires 这个属性来控制是否使用强缓存有一个坑,就是有时候服务器的时间和浏览器的时间可能并不一致。导致服务器返回的这个过期时间不准确。所以 Expires 很快在后来的 HTTP1.1 版本中被抛弃了。
Cache-Control
Cache-Control是HTTP/1.1中新增的属性。在请求头和响应头中都可以使用,它和
Expires本质的不同在于它并没有采用具体的过期时间点这个方式,而是采用过期时长来控制缓存,对应的字段是max-age。
Cache-Control:max-age=600上面代码代表服务器返回响应之后 10 分钟内可以直接使用缓存。
其他 Cache-Control 常用属性如下:
public:响应可以被中间代理、CDN 等缓存。
private:专用于个人的缓存,中间代理、CDN 等不能缓存此响应。
must-revalidate:在缓存过期前可以使用,过期后必须向服务器验证
no-store:禁止使用缓存。
no-cache: 跳过当前的强缓存,发送 HTTP 请求,即直接进入协商缓存阶段。
当 Expires 和 Cache-Control 同时存在的时候, Cache-Control 会优先考虑。
Pragma
Pragma是一个在HTTP/1.0中规定的通用首部,这个首部的效果依赖于不同的实现,所以在“请求-响应”链中可能会有不同的效果。它用来向后兼容只支持HTTP/1.0协议的缓存服务器,那时候HTTP/1.1协议中的Cache-Control还没有出来。Pragma只有一个属性值,就是no-cache,效果和Cache-Control中的no-cache一致,不使用强缓存,需要与服务器验证缓存是否新鲜。
注意
由于 Pragma 在 HTTP 响应中的行为没有确切规范,所以不能可靠替代 HTTP/1.1 中通用首部 Cache-Control,尽管在请求中,假如 Cache-Control 不存在的话,它的行为与 Cache-Control: no-cache 一致。建议只在需要兼容 HTTP/1.0 客户端的场合下应用 Pragma 首部。
2、协商缓存
当浏览器的强缓存失效,或者请求头中设置了不走强缓存的时候。浏览器在请求头中携带 If-Modified-Since 和 If-None-Match 这两个属性来向服务器发请求,由服务器根据这两个属性来决定是否使用缓存,这就是协商缓存。
Last-Modified
Last-Modified即最后修改时间,在浏览器第一次给服务器发送请求后,服务器会在响应头中加上这个字段,值为服务器返回数据的最后修改时间。浏览器接收到后,如果再次发起同一个请求,会在请求头中携带
If-Modified-Since这个字段,这个字段的值也就是服务器传来的最后修改时间。服务器拿到请求头中
If-Modified-Since字段后,就拿它的值与服务器中该资源的最后修改时间相比一下。如果请求头中的这个值小于最后修改时间,说明资源已经更新了。需要返回新的资源,跟常规的
HTTP请求响应的流程一样。否则说明资源没有发生改变,直接返回 304,告诉浏览器使用缓存。
ETag(资源唯一标识)
ETag是服务器根据当前文件的内容,给文件生成的唯一标识,只要里面的内容有改动,这个值就会改变。在浏览器第一次给服务器发送请求后,服务器会通过响应头把这个值(请求资源的ETag)给浏览器。浏览器接收到
ETag的值后,会在下次请求时将这个值作为If-None-Match这个属性的值放到请求头中,然后发给服务器。服务器接收到
If-None-Match后,会跟服务器上该资源的ETag进行对比。如果两者不一样,说明要更新了。返回新的资源,跟常规的
HTTP请求响应的流程一样。否则说明资源没有发生改变,直接返回 304,告诉浏览器使用缓存。
Last-Modified VS ETag(资源唯一标识)
在精准度上,ETag 优于 Last-Modified。因为 ETag 是按照内容给资源生成唯一标识,因此能准确感知资源的变化。而 Last-Modified 就不一样了,它在一些特殊的情况并不能准确感知资源变化,主要有两种情况:
1、如果文件的,
Last-Modified/If-Modified-Since会错误地返回 3042、的时候,Last-Modified/If-Modified-Since 也会错误地返回 304
在性能上,Last-Modified 优于 ETag,也很简单理解,Last-Modified 仅仅只是记录一个时间点,而 Etag 需要根据文件的具体内容生成哈希值。
russ