浏览器缓存

一、缓存类型

两种缓存策略:强缓存 和 协商缓存。

  1. 浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存,强缓存如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器。
  2. 当强缓存没有命中,浏览器发送一个请求到服务器,服务器判断这个资源是否命中协商缓存,如果协商缓存命中,服务器将这个请求返回,但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器就从缓存中加载这个资源;
  3. 当协商缓存也没有命中的时候,浏览器直接从服务器加载资源数据。

共同点:如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据;

区别:强缓存不会发请求,协商缓存会发请求。

二、强缓存

当浏览器对某资源的请求命中强缓存时,返回的HTTP状态为200,在控制台的network里的 size会显示为from cache。

强缓存实现方式:

  • Expires
  • Cache-Control

注意区分浏览器 加载资源时的请求 和 真正发送到服务器的请求 。

这两个http response header都用来表示资源在客户端缓存的有效期。Cache-Control优先级高于Expires,仅作为兼容性处理使用后者。

memory cache代表使用内存中的缓存,disk cache代表使用硬盘中的缓存,浏览器读取缓存的顺序为memory –> disk。

image-20200720120602458image-20200720123958430

1、Expires

  1. 概念:

    HTTP 1.0提出的表示资源过期时间的header,是一个绝对时间,由服务器返回,用GMT格式的字符串表示。

  2. 原理:

    1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上Expires;
    2. 浏览器在接收到这个资源后,会把这个资源连同所有response header一起缓存下来;
    3. 浏览器再加载这个资源时,先从缓存中找,找到后拿出它的Expires跟当前的请求时间比较,如果没过期就能命中缓存,否则就不行(所以缓存命中的请求,返回的header并不是来自服务器,而是来自之前缓存的header);
    4. 如果缓存没有命中,浏览器直接从服务器加载资源时,Expires Header在重新加载的时候会被更新。

2、Cache-Control

  1. 概念:

    HTTP 1.1提出的表示资源过期时间的header,是一个相对时间,由服务器返回,以秒为单位,用数值表示。

  2. 原理:

    1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上Cache-Control;
    2. 浏览器在接收到这个资源后,会把这个资源连同所有response header一起缓存下来;
    3. 浏览器再加载这个资源时,先从缓存中寻找,找到后根据它第一次请求时间和Cache-Control设定的时间,计算资源过期时间,再拿这个过期时间跟当前的请求时间比较,如果没过期就能命中缓存,否则就不行;
    4. 如果缓存没有命中,浏览器直接从服务器加载资源时,Cache-Control Header在重新加载的时候会被更新。
  3. 补充:Cache-Control 还可以配合多种指令使用。

    • private:表示该资源仅仅属于发出请求的最终用户,这将禁止中间服务器(如代理服务器)缓存此类资源。但 private 并不会使得缓存更加安全,它同样会传给中间服务器(如果安全性有要求,应该使用传输层安全措施),只是不缓存。
    • public:默认值,允许所有服务器缓存该资源。一般用于所有人都可以访问的资源(例如网站的 logo、图片、脚本等)。
    • 其他参考MDN。
    img

三、协商缓存

强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,两种情况:

  • 协商缓存生效,返回304和 Not Modified。
  • 协商缓存失效,返回200和请求结果。

协商缓存实现方式:

  • Last-Modified
  • ETag

这个时候是真的发送请求到服务器,要占用网络资源。

协商缓存跟强缓存不一样,强缓存不发请求到服务器,所以有时候资源更新了浏览器不知道,但是协商缓存会发请求到服务器,所以资源是否更新,服务器肯定知道。

1、Last-Modified

一般和其他首部配合使用,有 Last-Modified & If-Modified-Since 和 Last-Modified & If-Unmodified-Since,这里采用前者。

  1. 概念:响应首部,其中包含资源做出修改的日期及时间。 通常用于判断接收到的或者存储的资源是否彼此一致。

  2. 原理:

    1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上Last-Modified,表示资源最后修改时间。

    2. 浏览器再次跟服务器请求这个资源时,在 request 的 header 加上If-Modified-Since,值是上一次请求时返回的 Last-Modified 的值。

    3. 如果浏览器收到 304 ,就从缓存中加载资源;

      如果浏览器收到 200 ,就从服务器加载资源,并且 Last-Modified 在重新加载时会被更新,下次请求时,If-Modified-Since 就是上次返回的Last-Modified 的值。

  3. 补充:

    可能会出现服务器上资源有变化,但是最后修改时间没有变化的情况,精度低。

2、ETag

ETag & If-None-Match

  1. 概念:响应首部,资源的特定版本的标识符。如果给定URL中的资源内容更改,则一定要生成新的Etag值,跟最后修改时间无关。

  2. 原理:

    1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上 ETag,值是服务器根据当前请求的资源生成的一个唯一标识,是一个字符串。

    2. 浏览器再次跟服务器请求这个资源时,在request的header加上If-None-Match,值是上一次请求时返回的ETag的值。

    3. 服务器再次收到资源请求时,服务器只需要比较浏览器传来的 If-None-Match 跟自己服务器上该资源的 ETag 是否一致。

    4. 一致则返回 304、Not Modified 和 跟If-None-Match值一样的ETag,浏览器从缓存中加载资源;

      不同则返回 200 ,浏览器从服务器加载资源。

四、参考

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control

https://juejin.im/post/5b9346dcf265da0aac6fbe57

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Last-Modified

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/ETag

img

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

移动端适配 Previous
JavaScript运行机制 Next