前言
目前浏览器的缓存类型众多,HTTP Cache、Disk Cache、Memory Cache、ServiceWorker Cache、Push Cache 等等,这些缓存是如何产生的?命中优先级是怎么样?又该如何去使用它们?
Disk Cache、Memory Cache
Disk Cache、Memory Cache 属于强缓存,将缓存的响应写到内存或硬盘中,也属于 HTTP 缓存的产物。
强缓存是如何产生的?
强缓存的产生依赖于请求响应中的 cache-control
和 expires
的 headers 字段。这两个字段都是用来设置缓存数据的有效时间。
expires
是 HTTP 1.0 的产物,表示的是缓存的到期时间,是一个绝对时间。cache-control
是 HTTP 1.1 的产物,表示的是缓存的最大可用时长,是一个相对时间。
cache-control
字段的值,也需要搭配相应的字段来使用,常用字段:
max-age
:缓存的时长,和expires
的作用类似,单位是秒。no-cache
:忽略强缓存,真接走协商缓存。no-store
:忽略强缓存和协商缓存,直接从服务器获取响应。public
:所有的数据都可以被任意地方缓存(例如可以缓存到 CDN 和代理服务器上)。private
:默认值,所有内容只有客户端才可以缓存。
两个字段同时存在时,cache-control
优先级最高。
内存缓存和硬盘缓存如何存储的?
当请求响应符合强缓存时,浏览器会根据 header 头中的字段类型进行缓存处理。通常:
- 内存缓存:会存放 脚本、base64数据和字体等。
- 硬盘缓存:会存放 样式文件、图片或比较大的文件等。
此行为属于浏览器行为,服务器不可控。
区别
区别 | |
---|---|
Disk Cache | - 长期存在:浏览器关闭时同样存在。 - 存储文件空间更大。 |
Memory Cache | - 短期存在:生命周期为会话级的,回话结束 缓存清除。 - 访问速度更快。 - 优先级更高。 |
HTTP Cache
这里主要说的是返回状态码为 304
的这种协商缓存。
当强缓存失效后,浏览器就会携带缓存标志向服务器发送请求。这里主要用到的 header 头:
- Etag / If-None-Match
- Last-Modified / If-Modified-Since:
当收到请求的响应时,会携带:
- Etag:是服务器基于某种规则对资源生成的一个标志,类似于文件 hash。
- Last-Modified:是服务器返回文件最后修改的时间。
当发送请求的时候,浏览器会携带:
- If-None-Match:对应的就是 Etag 的值。
- If-Modified-Since:对应的就是 Last-Modified 的值。
服务器根据这两个值进行匹配,如果相等,说明文件没有变化,返回 304,浏览器直接从缓存里面取;当不相等时,服务器发送最新的内容,状态码为 200。
ServiceWorker Cache
ServiceWorker Cache 属于新的 PWA Cache Storage API,它有力度更细的程序可操作缓存的能力。
它的命中条件依赖于 fetch
,所以它的命中顺序如下:
是否从 serviceworker Cache 里面取缓存,完全依赖于 serviceworker 的脚本控制,取决于用户自定义。
浏览器上对应操作
强缓存 | serviceworker 缓存 | 协商缓存 | 缓存 headers 变动 | |
---|---|---|---|---|
刷新按钮 或 cmd + r | 有效 | 有效 | 有效 | 无变动 |
cmd + shift + r | 无效 | 无效 | 无效 | 请求中无 If-None-Match/If-Modified-Since ,Cache-Control 值为 no-cache 。 |
DevTools Network面板开启Disable cache | 无效 | 无效 | 无效 | 同上,但无缓存的能力更强 |