一、强缓存
强缓存就是本地缓存
浏览器首次请求资源后,需要再次请求时,浏览器会首先获取该资源缓存的 header 信息,然后根据 Cache-Control 和 expires 来判断该资源在本地缓存否过期。若没过期则直接从本地缓存中获取资源信息,浏览器就不再向服务器重新请求资源,如过期则需重新发送请求,重新缓存资源,更新缓存时间。
强缓存是利用 http 请求头中的 Expires 和 Cache-Control 两个字段来进行控制,用来表示资源的缓存时间。
- Expires
Expires 是 http1.0 的规范,它的值是一个 GMT 格式的绝对时间字符串。
expires: Thu, 17 Nov 2022 10:06:35 GMT
- Cache-Control
cache-control: max-age=31536000
Cache-Control 是 http1.1 中出现的,它的值是一个相对时间。Cache-Control 拥有多个值:
- private:客户端可以缓存
- public:客户端和代理服务器均可缓存
- max-age=xxx:缓存的资源将在 xxx 秒后过期
- no-cache:不进行强缓存,需要使用协商缓存来验证是否过期
- no-store:既不进行强缓存,也不进行协商缓存
Expires 和 Cache-Control 的区别?
首先一个是绝对时间一个是相对时间。绝对时间跟系统时间改变而改变,这说明可以人为的改变该时间。而相对时间则是固定时间,是从请求到资源的那一刻开始算起。 两个时间可以共存,Cache-Control 优先级更高
二、协商缓存
协商缓存是服务器用来确定缓存资源是否可用过期
因为服务器需要向浏览器确认缓存资源是否可用,二者要进行通信,而通信的过程就是发送请求,所以在 header 中就需要有专门的标识来让服务器确认请求资源是否可以缓存访问,所以就有了下面两组 header 字段:
- (http1.0) Last-Modified 和 If-Modified-Since
- 当浏览器第一次向服务器请求资源时,服务器会在该资源的请求头中加上 Last-Modify,Last-Modify 是该资源在服务器的最新修改时间,也就是说 Last-Modify 记录了该资源的最后一次创建、修改时间,保证服务器给浏览器的资源是最新的
- 然后当浏览器再次请求这个资源时,会在请求报文中带上 If-Modify-Since
- If-Modify-Since 是浏览器上一次请求该资源时返回的 Last-Modify 时间,也就是说 Last-Modify 和 If-Modify-Since 是同一个时间
- 当服务器收到 If-Modify-Since 时间后,会判断这个资源的当前最新修改时间和 If-Modify-Since 时间是否相等,相等则说明浏览器缓存的资源已经是最新的了,服务器返回 304 状态码告诉浏览器资源已是最新不用更新
- 不相等则说明在浏览器没有请求的这段时间,这个资源已经进行了修改、更新,浏览器本地缓存的这个资源已经不是最新的了,这时候服务器重新返回该资源的最新版以及最新的 Last-Modify 时间
- (http1.1) Etag 和 If-None-Match
- Etag/If-None-Match 和 Last-Modify/If-Modify-Since 的处理逻辑一致,通俗讲都是第一次请求给个标识,然后下一次请求再把这个标识传回去,服务器判断资源改变没有,改变了就重新返回,没有改变就返回 304,浏览器继续使用本地缓存。
Etag 表示文件在服务器的唯一标识(生成规则由服务器决定),在 iis 中由 FileTimeStamp(时间戳)和 ChangeNumber(修改编号),其中 FileTimeStamp 是类似 MD5 算法方式计算出来的,微软没有公布算法。
既然都是一样的处理逻辑,那这两个有什么不同吗?
说白了 Etag/If-None-Match 就是用来弥补 Last-Modify/If-Modify-Since 的不足
- Last-Modified 标注只能精确到秒级,如果某些资源在 1 秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
- 服务器资源增加了一个字符,后来又把这个字符删掉,本身资源文件并没有发生变化,但修改时间发生了变化,所以 Last-Modified 记录的时间改变了,导致资源刷新
- 有可能存在服务器没有准确获取资源的修改时间,或者与代理服务器时间不一致等情形
- Etag 是服务器自动生成或者由开发者生成的资源在服务器的唯一标识符,能够更加准确的控制缓存
- Etag/If-None-Match 的优先级高于 Last-Modify/If-Modify-Since