一.前言
- Web 服务缓存 ⼤致可以分为:数据库缓存、服务器端缓存(代理服务器缓存、CDN 服务器缓存)、浏览器缓存。
- 浏览器缓存 也包含很多内容: HTTP 缓存、indexDB、cookie、localstorage 等等。 这⾥我们只讨论 HTTP 缓存相关内容 。
- HTTP缓存: (优化⻚⾯加载的效率, 如果没有缓存策略, 每次重新加载⻚⾯, 会⾮常慢!)
- HTTP缓存分为 :
强制缓存、协商缓存
二. 强制缓存
1、进⾏判断缓存是否有效, 就是判断资源是否过期, 如果未过期, 直接⽤缓存
2、强制缓存是利⽤http的返回的响应头中的Expires或者Cache-Control (优先级更⾼) 两个字段来控制的,⽤来表示资源的缓存时间。
3、Expires: 指定⼀个具体时间(2020年12⽉12⽇ 17:00), 到了这个时间了, 缓存过期了, 在时间内, 都是有效的, 可以直接读
4、Cache-Control : 指定⼀个过期时间 (3600s), 这个资源你加载到后, 可以⽤ 3600s
1. Expires
2 .Cache-Control 
三. 协商缓存
1、若未命中强缓存(强缓存过期了),则浏览器会将请求发送⾄服务器。
2、服务器根据http头信息中的 Last-Modify/If-Modify-Since 或 Etag/If-None-Match 来判断是否命中协商缓存。
3、如果命中,则http返回码为304 (你本地之前加载的资源是有效的),浏览器从缓存中加载资源。
4、由于对⽐的是服务端的修改时间,所以就算客户端与服务端时间差距, 也不会有问题
5、但是有时候通过最后修改时间来判断资源是否修改还是不太准确(资源变化了最后修改时间也可以⼀致)。⽐如: Last-Modify/If-Modify-Since最后修改只能精确到秒级, ⼀秒进⾏了多次修改, 就不⾏了, 于是出现了ETag/If-None-Match。
6、与Last-Modify/If-Modify-Since (最后修改时间)不同的是,Etag/If-None-Match返回的是⼀个校验码(ETag: entitytag),ETag可以保证每⼀个资源是唯⼀的,资源变化都会导致ETag变化
1.last-modified
2.ETag
- ETag⽣成靠以下⼏种因⼦
- ⽂件的i-node编号,是Linux/Unix⽤来识别⽂件的编号。
- ⽂件最后修改时间
- ⽂件⼤⼩**
Etag的出现主要是为了解决⼏个Last-Modified⽐较难解决的问题:
- Last-Modified标注的最后修改只能精确到秒级; 如果某些⽂件在1秒钟以内,被修改多次的话,它将不能准确标注⽂件的修改时间 有可能存在服务器没有准确获取⽂件修改时间,或者与代理服务器时间不⼀致等情形
- 有可能存在服务器没有准确获取⽂件修改时间,或者与代理服务器时间不⼀致等情形;
Etag是服务器⾃动⽣成或者由开发者⽣成的对应资源在服务器端的唯⼀标识符,能够更加 准确的控制缓存。 不会仅仅只根据最后的修改时间判断是否进⾏使⽤缓存 Last-Modified与ETag是可以⼀起使⽤的,服务器会优先验证ETag,⼀致的情况下,才会继续⽐对Last-Modified, 最后才决定是否返回304。
四. 整体请求缓存流程
浏览器第一次请求:
浏览器第二次缓存:
总结:
强制缓存: 检查过期时间, 判断缓存是否失效, 如果不失效, 直接⽤, 不发请求; ⼤⼤的减少了 服务器的请求次数, 在过期时间内, 直接从客户端内存中读
协商缓存: 强缓存命中失效了, 超过过期时间了, 拿着标识(最后的修改时间, 唯⼀标识etag), 去问服务器, 是否真的过期了,如果验证通过,服务器会直接响应 304, 且不会返回资源。 比如:不太会变的资源 => 图⽚,⾮常的适合应⽤强缓存 (过期时间也可以设置的很⻓); 如果是⼀些很可能会变的资源, 也希望能缓存 => 过期时间设置短⼀些, ⼀旦过期, 协商缓存。实际⼯作两者相互配合