讲讲强缓存和协商缓存,F5 和 Ctrl + F5 的区别
本文参考: 深入理解浏览器的缓存机制
PS:本文面向面试题,所以只讲些知识点扫盲,详细分析自行查阅参考链接
基本概念
网上常讲的强缓存和协商缓存(也有叫对比缓存)都是浏览器的缓存策略
需要先明确一点,既然是浏览器的缓存,缓存的数据都是存放于客户端的机子上的,只是根据优先级不同,存储位置不同,还可以进行细分而已,比如 Service Worker,Memory Cache,Disk Cache
那么,强缓存和协商缓存的区别是什么?
就我个人理解,它们的区别其实在于交给谁来做决策,谁来决定是否要使用缓存
强缓存:浏览器在发请求前,会自行去做一些缓存判断工作,自行决定到底要不要发请求,要不要直接使用缓存
协商缓存:浏览器决定不了,必须发个请求给服务端,交由服务端来告知浏览器到底能不能使用缓存
所以,其实,对于强缓存来说,是有可能不用发请求的,体现在浏览器的开发者工具 Network 抓包中就是,size 一栏会明确显示该请求从本地缓存读取
对于协商缓存来说,请求是必须要发的,但服务端判定客户端可以使用缓存时,就不会返回响应体了,体现在响应头中就是 304
相关 header 字段
强缓存、协商缓存都是通过请求头和响应头中的字段来实现的,相关的 header 字段有:Expires,Cache-Control,Last-Modified,If-Modified-Since,ETag,If-None-Match
这些字段,有的是在请求头中使用,有的是在响应头里使用,下面就来讲讲:
- 请求头
1 | GET / HTTP/1.1 |
- 响应头
1 | HTTP/1.1 200 OK |
expires
1 | // 响应头 |
这是响应头中的字段, http 1.0 就有了,内容表示一个绝对时间,含义也就是缓存的到期时间
这样,当浏览器接收到这样的响应头,它就知道,这份资源的下次请求,只要在过期时间前,就没必要再发起请求,直接使用本地缓存即可
缺点则是,由于是绝对时间,需要依赖于客户端本地时间
Cache-Control
1 | // 请求头 |
这个是 http 1.1 新增的字段,请求头和响应头中都可以使用
这字段的内容有多个取值,不同取值对应不同缓存行为,客户端和服务端就是通过这字段来进行沟通缓存事宜
这里列举一些取值,更多请查阅 MDN
max-age:设置缓存最大有效期,相对时间,单位 s
must-revalidate:一旦缓存过期,需要重新向服务端发请求验证
no-cache:本地缓存能不能用,交由服务端决定,所以需先发请求给服务端
no-store:禁止缓存,不使用缓存,包括内存、磁盘缓存
public:代理和客户端都可以缓存
private:只有客户端可以缓存,代理不能缓存
这个字段其实就是用来替代 http 1.0 中的 Expires 字段
开头所说的强缓存、协商缓存也是通过这个字段来实现,比如当响应头中带有 Cache-Control: max-age=60
,浏览器如果发现在缓存过期前再次请求该资源,就可以直接使用本地缓存了,这就是强缓存
当响应头中带有 Cache-Control: no-cache
时,浏览器就知道,本地的缓存它做不了主,需要它再次向服务端发请求确认是否可以使用本地缓存
Last-Modified & If-Modified-Since
强缓存时,浏览器可以直接自行决定是否使用本地缓存,但协商缓存时,是需要跟服务端进行交互,那么,服务端是如何确认客户端的缓存是否可用的呢?
这就是这两字段的用途了,其中 Last-Modified 是响应头中的字段,服务端返回给客户端资源时,可用携带上该字段,表明这份资源最近一次更新的时间
1 | // 响应头 |
而当浏览器向服务端协商本地缓存是否可用时,就需要把本地缓存的资源中记录的 Last-Modified 值写入请求头的 If-Modified-Since 字段中,服务端接收到后,读取该字段值,就可以去进行验证了,如果客户端可使用缓存,那么就返回 304,否则返回 200 将新资源下发
ETag & If-None-Match
Last-Modified 的协商方式有些局限性,比如当资源的更新是秒级别以内时,或者资源文件确实有改动,但内容没变化时,这些场景,它无法识别出来
所以,引入的 ETag 和 If-None-Match 字段可以用来弥补这些场景
1 | // 响应头 |
同样,ETag 是响应头中的字段,If-None-Match 是请求头中的字段
服务端可以对资源内容生成 hash 值返回给客户端,一旦资源内容更新,hash 值也就不一样了,客户端的请求中携带了缓存资源的 hash 值,服务端通过比对,就可以确认资源是否有发生变化,就可以告知客户端是否可以直接使用缓存
但相对而言,较耗性能
用户行为
用户有三种行为会涉及到缓存:
- 新打开 Tab,输入 url,加载网页
- F5 刷新或者地址栏回车(等同于F5)
- Ctrl + F5 刷新
当新打开一个 Tab 来加载网页,或者在当前 Tab 输入新的 url 加载新网页时,此时浏览器的内存缓存就没有使用场景了,缓存策略就是根据相关 header 字段来决定是走强缓存还是协商缓存
F5 刷新页面时,如果允许缓存,那么会优先从内存缓存中寻找,再根据 header 字段来判断走强缓存还是协商缓存
Ctrl + F5 也叫强制刷新,此时发给服务端的请求头中不会携带 If-Modified-Since 或 ETag 字段,那么服务端自然只能重新下发资源
知识点
面试时遇到该题,记住这些知识点,然后根据需要,扩展来讲:
强缓存、协商缓存
Expires、Cache-Control
Cache-Control 的几种取值
- no-cache
- max-age
- no-store
Last-Modified & If-Mofidied-Since
ETag & If-None-Match
F5 & Ctrl + F5