深入理解强缓存与协商缓存

687 阅读3分钟

写在文首

这两篇文章讲的非常透彻,大家都可以去学习一下

github.com/yiliang114/…

github.com/amandakelak…

下文有部分搬运


浏览器缓存的几个优点

  • 减少重复数据请求,避免通过网络再次加载资源,节省流量
  • 降低服务器压力,提升网站性能
  • 加快客户端加载网页的速度,提升用户体验

缓存基本原理

  • 浏览器在加载资源时,根据请求头的expirescache-control来判断是否命中强缓存,是则直接从缓存中读取资源,不发送请求到服务器
  • 如果没有命中强缓存,浏览器会发送请求至服务器,通过last-modifiedetag验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,但是不会返回这个资源的数据,依然是从缓存中读取数据
  • 如果前面两者都没有命中,直接从服务器加载资源

强缓存与协商缓存的异同

  • 相同点:如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据
  • 不同点:强缓存不发请求到服务器,协商缓存会发请求到服务器

请求流程

在这里插入图片描述


强缓存

强缓存根据返回头中的expirescache-control两个字段控制,都表示资源的缓存有效时间。

  • Expires 是 http 1.0 的规范,值是一个GMT 格式的时间点字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT 。这个时间点代表资源失效的时间,如果当前的时间戳在这个时间之前,则判定命中缓存。有一个缺点是,失效时间是一个绝对时间,如果服务器时间与客户端时间偏差较大时,就会导致缓存混乱。而服务器的时间跟用户的实际时间是不一样是很正常的,所以 Expires 在实际使用中会带来一些麻烦。
  • Cache-Control 这个字段是 http 1.1 的规范,一般常用该字段的 max-age 值来进行判断,它是一个相对时间,比如 .Cache-Control:max-age=3600 代表资源的有效期是 3600 秒。并且返回头中的 Date 表示消息发送的时间,表示当前资源在 Date ~ Date +3600s 这段时间里都是有效的。不过我在实际使用中常常遇到设置了 max-age 之后,在 max-age 时间内重新访问资源却会返回 304 not modified ,这是由于服务器的时间与本地的时间不同造成的。当然 Cache-Control 还有其他几个值可以设置, 不过相对来说都很少用了
  • 如果expires和cache-control同时存在,cache-control的优先级更高

协商缓存

协商缓存最终由服务器来决定是否命中 ,利用的是【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】两对header进行控制。

  • Last-Modified标记了文件最后的修改时间,在请求头中会带有If-Modified-Since字段,通过比较这两个字段来判断文件有没有发生过变化。如果没有变化则返回304 Not Modified
  • Etag是服务器中每一个资源生成的唯一标识符,只要资源有变化这个值就会改变。通过比较请求头的If-None-Match字段判断文件是否有变化。

Etag优先级高于Last-Modified

  • Last-modified的值只精确到秒级,若一个文件已毫秒级的速度进行更新,则会产生误判
  • 文件若每隔一段时间都重复生成,但是内容相同,只有最后修改时间进行了变化,这种情况我不希望客户端认为这个文件被修改了

优先级

cache-control > expires > etag > last-modified