强缓存和协商缓存是浏览器缓存机制中的两种常见策略,用于提高网页加载速度和减少网络流量。他们也是前端面试中经常考到的计网相关知识点,今天我们一起来梳理学习一下。
🐘 强缓存
强缓存的含义是,客户端发送请求时,会先访问缓存数据库,存在就直接返回,否则再向服务器发送请求。
可以造成强缓存的字段是 cache-control
和 Expires
.
Expires表示缓存到期的时间,是一个绝对的时间.
Expires: Thu, 10 Nov 2017 08:45:11 GMT
缺点:
- 由于是绝对时间,考虑到时差/误差或者客户端自行修改等因素,都会造成客户端与服务器端时间不一致,从而导致缓存失效。
- 字段表示过于复杂,很容易因为非法属性值从而设置失效
cache-control 则是通过设置相对时间来修正 Expires
的缺点.
Cache-control: max-age=2592000
更多常用的字段
max-age
:即最大有效时间,在上面的例子中我们可以看到must-revalidate
:如果超过了max-age
的时间,浏览器必须向服务器发送请求,验证资源是否还有效。no-cache
:虽然字面意思是“不要缓存”,但实际上还是要求客户端缓存内容的,只是是否使用这个内容由后续的对比来决定。no-store
: 真正意义上的“不要缓存”。所有内容都不走缓存,包括强制和对比。public
:所有的内容都可以被缓存 (包括客户端和代理服务器, 如 CDN)private
:所有的内容只有客户端才可以缓存,代理服务器不能缓存。默认值。
🦄 协商缓存
当强制缓存失效(超过规定时间)时,就需要使用协商缓存,由服务器决定缓存内容是否失效。
大致流程如下:浏览器先请求缓存数据库返回一个缓存标识,随后携带这个缓存标识与浏览器通讯,如果未失效则返回 304 继续使用,否则返回新的数据与缓存规则。
协商缓存具有两组字段:
Last-Modified & If-Modified-Since
- 服务器通过
Last-Modified
告知客户端,资源最后一次被修改的时间. - 浏览器将这个值和内容一起记录在缓存之中.
- 下一次请求相同资源而强缓存失效时,会在请求头中设置
If-Modified-Since
的值为缓存中记录的Last-Modified
. - 服务器会将
If-Modified-Since
的值与Last-Modified
字段进行对比。如果相等,则表示未修改,响应 304;反之,则表示修改了,响应 200 状态码,并返回数据。
缺陷如下:
- 如果资源更新的速度是秒以下的单位,那么该缓存是无法使用的。
- 如果文件是通过服务器动态生成的,那么该方法的更新时间永远是生成的时间,尽管文件可能并没有改变,但仍然会被认为改变了。
Etag & If-None-Match
为了解决上述问题,出现了这一组新的字段。
Etag
存储文件的特殊标识(通常由hash生成),流程基本一致。
🎯 策略选择
- 强缓存适用于那些不经常更新的静态资源,例如图片、样式表等。它可以减少对服务器的请求,提高网页加载速度。
- 协商缓存适用于那些经常更新的资源,例如动态生成的内容或者频繁变动的数据。它可以通过与服务器进行通信来判断资源是否有更新,从而决定是否使用缓存。
📝 小结
如果有强制缓存且未失效,则使用强制缓存,不请求服务器,状态码均为 200.
如果有强制缓存但已失效,则使用协商缓存,比较 时间 或 Etag 确定是 304 还是 200.