概述
前端缓存分为 HTTP 缓存和浏览器缓存
HTTP 缓存又分为强制缓存和协商缓存
客户端请求资源简单过程
- 首次请求时,服务器返回资源,并在响应头中注明缓存参数,客户端缓存资源
- 再次请求时,会先访问浏览器缓存,若命中强缓存则直接提取资源,状态码返回 200
- 若未命中强缓存,则将请求发送给服务器,判断本地协商缓存是否失效,若有效则返回状态码 304
- 若未命中协商缓存,则服务器返回完整资源,并更新缓存
强缓存
强缓存的特点是 请求时无需访问服务器
加载速度最快,性能最好
命中时直接返回成功 200
- 强缓存由响应头中的 Expires 或 Cache-Control 两个字段控制,表示缓存有效期
- 还有一个已经在 HTTP/1.1 被废弃的 Pragma
Pragma
现在为了兼容 HTTP/1.0 而使用,并且响应头中不支持这个属性,但它的优先级最高
- 可选值 no-cache — 不直接使用缓存,需先询问服务器,即不使用强缓存
Expires
适用于 HTTP/1.0 和 HTTP/1.1,指示缓存过期时间,与 last-modified 一起使用
缺点是若客户端和服务端时间不一致会导致缓存更新不及时
- expires 表示缓存到期时间,如图所示,这个资源在 2023 年 1 月 29 日 19 点 0 分 46 秒之前都是有效的
- last-modified 表示缓存资源上一次修改时间
Cache-Control
不适用于 HTTP/1.0,缓存有效时间是一个相对时间 max-age,是以用户发起请求的时间为起点,单位是秒,图中表示在发起请求的一年后过期
可选值
- no-cache
- no-store — 不使用缓存,每次都重新请求资源
- max-age — 缓存有效时长,相对时间,单位是 s
- public / private — 是否只能给单个用户使用,默认为 private
- must-revalidate — 每次访问需缓存校验
注意:Cache-Control 和 Expires 同时启用时,前者的优先级更高,即优先使用 Cache-Control
协商缓存
未命中强缓存时,需访问服务器确认当前浏览器的缓存是否过期,若未过期则直接读取,返回 304
什么时候会不命中?
- 响应头中没有 Cache-Control 和 Expires
- Cache-Control 和 Expires 过期
- Pragma 或 Cache-Control 属性设置为 no-cache
相关响应头字段
Last-Modify/If-Modify-Since
last-modified 是一个 GMT 表示最后修改时间,第一次请求资源时返回
- 客户端发起请求时,在请求头中包含字段 If-Modify-Since,服务器收到后与该资源的最后修改时间来确定是否使用缓存
- 若资源未过期,则返回 304 表示资源未修改
- 若资源已过期,则返回 200 并附上最新资源以及新的 last-modified
Etag/If-None-Match
Etag 可以保证每个资源时唯一的,资源的每一次变化都会导致 Etag 值变化
- 客户端发起请求时,在请求头中包含字段 If-None-Match,服务器收到后与该资源的当前的 Etag 来确定是否使用缓存
- 若资源未过期,则返回 304 表示资源未修改,直接访问缓存
- 若资源已过期,则返回 200 并附上最新资源以及新的 last-modified
Last-modified 无法精确到秒级,所以诞生了 Etag
若资源的内容没变但是时间变了,Last-modified 会产生变化而无法使用缓存,而 Etag 不会
总结
- Web 缓存利用 HTTP 缓存来减少访问未被修改的资源,实现页面的快速加载
- HTTP 缓存主要由 强缓存(强制缓存)和协商缓存
- 强制缓存在规定时间内有效,可直接使用,且状态码为 200,若已失效则执行协商缓存
- 协商缓存利用发送给服务器特定字段,由服务器对字段进行校验,来确定是否使用缓存,可使用则状态码为 304