求star

开源不易,喜欢请点个star吧

Ocean Han
1295 字
6 分钟
强缓存与协商缓存
TIP

浏览器缓存是浏览器在本地磁盘对用户最近请求过的资源进行存储,当再次访问统一资源时,就可以直接使用缓存,可以减少与服务器的数据传输,减小服务器的负担,提高页面响应速度等

请求过程#

TIP

浏览器在第一次请求后缓存资源,再次请求时,会进行下面两个步骤:

  • 浏览器发起对于某资源的请求时,会先检查本地是否存在缓存,如果存在则通过expirescache-control检查缓存是否有效,如果命中缓存且缓存未过期,则不会向服务器发起请求,直接使用缓存资源
  • 若未命中本地缓存,浏览器就会向服务器发送一个协商请求,通过Last-Modified-Since或者IF-None-Match(这两个字段的值,分别是第一次请求返回的Last-Modified/Etag)来向服务器验证是否命中协商缓存 :
    • 如果命中,服务器会返回304状态码,且此次响应不会返回资源内容,浏览器直接使用缓存
    • 如果未命中,服务器则会返回200状态码,并返回资源的实际内容,同时更新header中的字段

强缓存:package:#

TIP

​ 强缓存是通过ExpiresCache-Control来控制缓存在本地的有效期的

Expires#

TIP

ExpiresHTTP1.0提出的一个表示资源过期时间的request header,它描述的是一个绝对时间,由服务器返回。Expires受限于本地时间,如果修改本地时间,可能会造成缓存失效。对于一个资源的请求,如果在Expires内,则浏览器会直接使用缓存,不请求服务器

​ 格式如下:

Expires: Sun, 14 Jun 2020 02:50:57 GMT

Cache-Control#

TIP

Cache-Control出现于HTTP1.1,优先级高于Expires,它描述的是相对时间,请求头和响应头都支持这个字段,用来定义缓存策略

​ 格式如下:

Cache-Control: max-age=300
TIP
  • Cache-Control: no-store: 禁止浏览器缓存数据,每次请求资源都会向服务器要完整的资源
  • Cache-Control: no-cache: 不使用本地缓存,需要使用协商缓存
  • Cache-Control: public | private:
    • private: 默认值。表示只能应用于浏览器私有缓存中
    • public: 表示该响应可以被任何中间人,中间代理,CDN等缓存。
  • Cache-Control: max-age=xxx: 响应的最大过期时间,单位是s。表示资源能够被缓存的时间(即保持新鲜的最大事件),max-age是距离请求发起的时间的秒数
  • Cache-Control: must-revalidate: 当使用了must-revalidate指令,那就意味着缓存在考虑使用一个陈旧的资源时,必须先验证它的状态,已过期的缓存将不被使用。在正常情况下是没有必要使用这个指令的,因为在强缓存过期的情况下会进行协商缓存,但是HTTP规范是允许客户端在某些特殊情况下直接使用过期缓存的,比如校验请求发送失败的时候,还比如有配置一些特殊指令stale-while-revalidatestale-if-error等的时候,must-revalidate指令就是让缓存在过期后的任何情况下都必须重新验证。

协商缓存:package:#

TIP

​ 当浏览器对某个资源的请求没有命中强缓存,就会发送一个请求到服务器,验证协商缓存是否命中,如果协商缓存命中,请求响应返回的状态码为304(Not Modified),该请求不携带实体数据;若未命中,则返回200状态码并携带资源实体数据。

​ 协商缓存主要利用的是Last-Modified、IF-Modified-SinceETag、IF-None-Match这两对字段来控制的。

Last-Modified、IF-Modified-Since#

TIP

​ 在HTTP1.0引入。Last-Modified表示本地文件的最后修改日期,浏览器会在请求头上加上IF-Modified-Since(也就是上次相应的Last-Modified的值),来询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来。

​ 但是,如果在本地打开缓存文件,就会导致Last-Modified被修改,所以在HTTP1.1出现了ETag

ETag、IF-None-Match#

TIP

ETag服务器为资源生成的唯一标识串,资源发生变化会导致Etag变化,跟最后修改时间没有关系,所以ETag可以保证每个资源是唯一的。IF-None-Match的请求字段会将上次返回的ETag发送给服务器,来询问该资源的ETag是否有更新,如果有变动就会发送新的资源回来。

ETag的优先级比Last-Modified高,在以下类似情况,应该优先使用ETag:

  • 一些文件也许会周期性的更改,但是他的内容并不改变,比如仅仅改变的修改时间,这个时候我们并不希望客户端认为这个文件被修改了,而重新GET
  • 某些文件修改非常频繁,比如在秒以下的时间内进行修改,例如1s内修改了N次,If-Modified-Since能检查到的粒度是秒级的,这种修改无法判断
  • 某些服务器不能精确的得到文件的最后修改时间
强缓存与协商缓存
https://blog.oceanh.top/posts/network/强缓存与协商缓存/
作者
Ocean Han
发布于
2023-03-10
许可协议
CC BY-NC-SA 4.0
最后修改时间
2024-08-10 10:08:49