缓存位置

  • service worker(https)
  • memory cache(不受 Cache-Control 的值影响)
  • disk cache
  • push cache(属于 http2 的功能,不受 http header 控制)

注意 disk cache:

1、对于大文件来说,大概率是不存储在内存中的,反之优先

2、当前系统内存使用率高的话,文件优先存储进硬盘

缓存机制

强制缓存

强缓存:不会向服务器发送请求,直接从缓存中读取资源,在 chrome 控制台的 Network 选项中可以看到该请求返回200的状态码,并且Size 显示 from disk cache 或 from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。

其实这两者差别不大,区别就在于 Expires 是 http1.0 的产物,Cache-Control 是 http1.1 的产物,两者同时存在的话,Cache-Control 优先级高于 Expires;在某些不支持 HTTP1.1 的环境下,Expires 就会发挥用处。所以 Expires 其实是过时的产物,现阶段它的存在只是一种兼容性的写法。

协商缓存

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

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

协商缓存可以通过设置两种 HTTP Header 实现:Last-Modified 和 ETag 。

但是 Last-Modified 存在一些弊端:

  • 如果本地打开缓存文件,即使没有对文件进行修改,但还是会造成 Last-Modified 被修改,服务端不能命中缓存导致发送相同的资源
  • 因为 Last-Modified 只能以秒计时,如果在不可感知的时间内修改完成文件,那么服务端会认为资源还是命中了,不会返回正确的资源

ETag 和If-None-Match 可以直接根据文件内容是否修改来决定缓存策略。

首先在精确度上,Etag 要优于 Last-Modified。
Last-Modified 的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的 Last-Modified 其实并没有体现出来修改,但是 Etag 每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。

第二在性能上,Etag 要逊于 Last-Modified,毕竟 Last-Modified 只需要记录时间,而 Etag 需要服务器通过算法来计算出一个 hash值。
第三在优先级上,服务器校验优先考虑 Etag

深入理解浏览器的缓存机制