前言
客户端向服务器请求数据时,会先查看浏览器缓存,如果浏览器有这个需要请求的资源的副本,就可以直接从浏览器的缓存中提取这个资源,而不需要重新请求。
但是,如果浏览器每次都使用缓存中的资源而不再发送请求,这样也可能导致获取到的资源不是最新的,所以浏览器缓存有如下两种策略:
1.强缓存
2.协商缓存
1、强缓存
定义:当发起HTTP请求时,不会向服务器直接进行请求,而是只要当前时间在缓存有效期内,则直接从客户端缓存中获取,当缓存过期后,才会真正向服务器发起请求重新获取资源。
强缓存主要是浏览器根据请求头部的两个字段来判断的:
1.expires(HTTP/1.0)
2.cache-control(HTTP/1.1)
1)Expires
Expires
即过期时间,存在于服务端返回的响应头中,告诉浏览器在这个过期时间之前可以直接从缓存里面获取数据,无需再次请求。比如下面这样:
Expires: Wed, 22 Nov 2021 08:42:00 GMT
// 表示资源在2019年11月22号8点41分过期,过期了就得向服务端发请求。
缺点:由于使用具体时间,如果时间表示出错、服务器的时间和浏览器的时间不一致或者没有转换到正确的时区都可能造成缓存生命周期出错。因此这种方式很快在后来的HTTP1.1版本中被抛弃了。
2)Cache-Control
Cache-Control
是HTTP1.1为了弥补Expires的缺陷而加入的。浏览器的请求头和服务器的响应头中都有这个字段。
优先级: 当Expires和Cache-Control同时存在时,Cache-Control优先级高于Expires
它和Expires区别:它并没有采用具体的过期时间点这个方式,而是采用过期时长来控制缓存,对应的字段max-age
。
Cache-Control:max-age=3600
// 表示这个响应返回后3600秒,也就是一个小时之内有效
其他配置:
属性 | 描述 |
---|---|
max-age | 设置缓存存储的最大周期,超过这个时间缓存被认为过期(秒) |
public/private | public表示客户端和代理服务器都能缓存; private表示只能用户的浏览器才能缓存 |
no-cache | 跳过当前的强缓存,发送HTTP请求(即直接进入协商缓存阶段) |
no-store | 不强缓存,也步协商缓存 |
must-revalidate | 缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源 |
缺点:如果服务器资源更新了,或者修正了一个bug,而强缓存时间太长,就会造成客户端更新落后.
2、协商缓存
当缓存资源过期了,也就是强缓存失效了,浏览器就会调用协商缓存策略
定义:浏览器在请求头中携带相应的缓存tag来向服务器发请求,由服务器根据这个tag,来决定是否使用缓存.
缓存tag分类:
1.last-modified
2.Etag
1)Last-Modified
last-modifies
: 即最后修改时间,在浏览器第一次向服务器发送请求后,服务器会在响应头中加上这个字段.
下次请求时,浏览器会在请求头携带If-Modified-Since
字段,其值就是服务器传来的最后修改时间last-modified
.
服务器拿请求头中的If-Modified-Since
的字符后,其实会和这个服务器中的该资源的最后修改时间对比:
1.如果请求头中的这个值小于最后修改时间,说明是时候更新了.返回新的资源,跟常规的HTTP请求响应的流程一样,返回200及请求结果
2.否则返回304,告诉浏览器直接使用缓存
2)ETag
ETag
:是服务器根据当前文件的内容,给文件生成的唯一标识,只要里面的内容有改动,这个值就会变,服务器通过响应头把这个值给浏览器
浏览器接受到ETag的值,会在下次请求时,将这个值作为If-None-Match
这个字符的内容,放入请求头中,然后发给服务器.
服务器接收到If-None-Match
后,会跟服务器上该资源的ETag进行对比:
1.如果两者不一样,说明更新了,返回新的资源,跟常规的HTTP请求响应的流程一样
2.否则返回304,告诉浏览器直接用缓存
3、比较last-modified和etag
-
资源仅仅改变修改时间,内容不变,这个时候last-modified会造成缓存失败而etag不会
-
last-modified能够感知的单位时间是秒,当文件在1秒内修改了多次,last-modified会触发缓存,而etag不会
-
如果同时设置了last-modified和etag,服务器会优先考虑etag
4、强缓存和协商缓存的对比
缓存类型 | 获取资源形式 | 状态码 | 发送请求到服务器 |
---|---|---|---|
强缓存 | 从缓存取 | 200 | 否,直接从缓存取 |
协商缓存 | 从缓存取 | 304 | 是,通过服务器来告知缓存是否可用 |
5、总结
HTTP缓存都是从第二次请求开始的.
- 第一次请求资源时,服务器返回对应资源,并在响应头中携带缓存数据(如:Expires, cache-control, last-modified, Etag)
- 第二次请求,浏览器首先通过
Cache-Control
验证强缓存是否可用:-
- 可用,直接使用缓存
-
- 否则进入协商缓存,即发送HTTP请求,服务器通过请求头中的
If-Modified-Since
或者If-None-Match
字段检查资源是否更新
-
- 若资源更新,返回资源和200状态码
-
- 否则,返回304,告诉浏览器直接从缓存获取资源
- 否则进入协商缓存,即发送HTTP请求,服务器通过请求头中的
-