ChuChencheng / note

菜鸡零碎知识笔记
Creative Commons Zero v1.0 Universal
3 stars 0 forks source link

浏览器缓存机制 #36

Open ChuChencheng opened 4 years ago

ChuChencheng commented 4 years ago

思维导图

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

跟着这篇文章整理的

浏览器缓存

缓存位置

1. Service Worker

2. Memory Cache

内存中的缓存。

3. Disk Cache

硬盘中的缓存。

关于哪些文件会缓存在内存、哪些在硬盘中:

4. Push Cache

缓存类型

浏览器根据请求资源时返回的响应头来判断资源是否该缓存; 根据请求头与响应头判断如何使用缓存。

1. 强缓存

不会发起请求,直接从缓存中读取资源,在 Devtool 中可以看到资源请求返回 200 状态码, Size 显示 from disk cache 或 from memory cache

通过设置 ExpiresCache-Control 两个 header 实现

Expires

Cache-Control

指令:

  1. public: 客户端与代理服务器都可缓存,例如 Server -> Proxy -> Browser ,设置了 public 后, Proxy 也可以缓存资源,下次 Browser 请求同一个资源时, Proxy 可直接返回缓存的资源而不用向 Server 请求
  2. private: 只有客户端可以缓存资源
  3. no-cache: 客户端在使用缓存之前,会经过协商缓存来判断资源是否与服务端一致,即会发起请求
  4. no-store: 不缓存资源,即不使用强缓存,也不使用协商缓存
  5. max-age: 缓存内容将在指定秒数后失效
  6. s-maxage: 只在代理服务器中生效,优先级高于 max-age ,如果存在则会覆盖 max-age 和 Expires
  7. max-stale: 表示客户端愿意接收一个已经过期的响应,在过期后指定秒数内可使用缓存
  8. min-fresh: 表示客户端不愿接受新鲜度不高于当前 age + min-fresh 设定秒数 的响应

两者对比

Expires 与 Cache-Control 区别在于,前者是 HTTP/1.0 的产物,二者同时存在时, Cache-Control 优先级更高。在不支持 HTTP/1.1 的环境下则 Expires 有效。现阶段 Expires 只是一种兼容的写法。

强缓存是基于时间来判断是否使用缓存,而不关心服务端文件是否已经更新,这可能导致拿不到最新的文件。

2. 协商缓存

在强缓存失效后,就会使用协商缓存; 协商缓存会发起请求,由服务器根据缓存标识决定是否使用缓存; 如果协商缓存有效,则响应 304 状态码, Not Modified 并且不会发送资源,否则会返回 200 状态码与请求资源结果。

协商缓存可以通过两对 headers 实现:

Last-Modified 和 If-Modified-Since

Last-Modified 记录文件在服务器上的最后修改时间,当浏览器请求这个文件时,会带上 Last-Modified 请求头。

当浏览器下次请求这个资源时,如果有 Last-Modified 请求头,则会添加 If-Modified-Since ,值为 Last-Modified 的值。

当服务器收到请求时,会将浏览器发送的 If-Modified-Since 值与请求资源的最后修改时间进行对比,如果没有变化,则返回 304 使用缓存;如果小于服务器中这个资源的最后修改时间,则表示文件有更新,返回新的资源和 200 。

缺陷:

ETag 和 If-None-Match

ETag 是服务端返回的当前资源的唯一标识(服务端生成),只要资源有变化,则 ETag 会重新生成。

浏览器下次请求缓存文件时,会把上一次的 ETag 放入 If-None-Match 中,服务端接收到请求后,会对比 If-None-Match 与服务器上文件的 ETag ,来判断该资源是否有更新。

ETag 的优势在于精确度高于以秒为精度的 Last-Modified

其缺点则是服务端要计算 hash 要耗费性能

在优先级上,服务器优先考虑 ETag

应用场景

没有一个绝对通用的缓存策略,只有根据不同的场景来使用不同的策略才能发挥缓存的作用。

1. 频繁变动的资源

对于频繁变动的资源,使用 Cache-Control: no-cache ,这样,浏览器每次请求此类资源都会发起请求,配合 ETag 或 Last-Modified 来验证缓存资源是否有效。

此做法不能节省请求,但可以减少响应数据的大小。

2. 不常变化的资源

对于这类资源通常使用 Cache-Control: max-age=31536000 ,配置一个较大的 max-age ,这样浏览器会使用强缓存,而不会发起请求。

如果遇到文件更新,则通过改变文件名的方式更新,旧的资源则因 URL 不同,不会再被请求而弃用。

这个场景在平时用得比较多,例如线上引用的 JS、CSS 等资源,在文件名后面都会加上一个 hash 值。

用户触发缓存行为

关于缓存的其他知识

这部分与浏览器或许不是很相关

缓存的特征

1. 命中率

衡量缓存是否有效的重要指标

命中率=返回正确结果数/请求缓存次数

2. 最大元素

能存放缓存的最大个数,超过这个数量,则会触发清空策略

合理设置最大元素值可提高缓存的命中率

3. 清空策略

一些简单的策略:

参考