HTTP 缓存分为强缓存和协商缓存.

HTTP 缓存控制机制

  • HTML Meta 标记

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
// 当前页面不缓存, 每次访问都去服务器拉取. 只有部分浏览器支持.
  • HTTP 头信息

HTTP 头信息

强缓存 (200 from cache)

判断的字段: expire 或 cache-control

  • expire [http 1.0 的标准],  存储的是过期的具体时间
  • cache-control  [http 1.1 的标准]  max-age 值是过期的秒. max-age  最大值不能超过1年. 秒为单位. 优先级高, 以它的结果为准.

由于具体时间没有转换到正确的时区有可能造成错误. 所以倾向于使用 cache-control: max-age

如果强缓存没有命中的话, 则进入协商缓存

协商缓存  (304 or 200)

判断的字段: last-modified 或 Etag

last-modified/If-Modified-Since

  1. 浏览器第一次请求数据之后,服务端在 Response Headers 会带上 Last-modified (服务端资源最后修改时间).

HTTP 缓存_修改时间


  1. 再次请求时, 请求头会带上 If-Modified-Since 去跟服务器资源的最后修改时间对比. 如果修改, 返回 200 , 否则返回 304 .

HTTP 缓存_修改时间_02

Etag/If-None-Match

  1. 第一次请求数据的时候, Response Headers 带上 ETag . (Etag 由服务端生成一段 hash 字段)
  2. 之后的请求带上 If-None-Match: 原Etag 的值.

last-modified 和 Etag 区别

  • 有些服务无法精确的得到资源最后修改时间.
  • last-modified 只能精确到秒.
  • 一些资源的最后修改时间改变了,但是内容没改变,使用 Last-modified 看不出内容没有改变。
  • Etag 的精度比 Last-modified 高,属于强验证. 优先级高

last-modified 和 Etag 优先级

先判断 Etag, 再判断 last-modified. 但是结果会由服务器决策.

一张图总结流程:

HTTP 缓存_修改时间_03

Service Worker 缓存

浏览器的请求过程

我们可以在 Chrome 的开发者工具中,Network -> Size 一列看到一个请求最终的处理方式:如果是大小 (多少 K, 多少 M 等) 就表示是网络请求,否则会列出 from memory cache, from disk cache 和 from ServiceWorker。一个请求在查找资源的过程中经过的缓存顺序

  • Service Worker、
  • Memory Cache(内存)
  • 像一些 prefetch 资源也会暂存在内存中.
  • HTTP Cache/Disk Cache (硬盘上的缓存)
  • Push Cache

一般资源会存入内存. 如果内存不够, 会释放一些.

  1. 首次请求

HTTP 缓存_缓存_04

走网络请求


  1. 再次请求 (F5)

HTTP 缓存_修改时间_05

三个请求都来自 memory cache。因为我们没有关闭 TAB,所以浏览器把缓存的应用加到了 memory cache。(耗时 0ms,也就是 1ms 以内)


  1. 关闭 TAB,打开新 TAB 并再次请求

HTTP 缓存_缓存_06


  1. 因为关闭了 TAB,memory cache 也随之清空。但是 disk cache 是持久的,于是所有资源来自 disk cache。(大约耗时 3ms,因为文件有点小) 而且对比 2 和 3,很明显看到 memory cache 还是比 disk cache 快得多的。

用户行为与浏览器缓存

  • F5 刷新, 内存不见, 协商缓存依然存在
  • 强制刷新/控制台强制清除缓存  内存不见, 协商缓存也存在
  • 地址栏访问, 回车, 前进后退. 缓存都不在.

缓存日常实践

  1. 永久缓存:  带 hash 值的静态 js, css资源永久缓存. cache-control : max-age=3153600  一年过期时间
  2. 对 index.html 使用 Cache-Control: no-cache

幸运的是,关于协商缓存你无需管理,无需配置, nginx 或者一些 OSS 都会自动配置协商缓存,而对于协商缓存,也有它们自己的算法。协商缓存背后是基于 Last-Modified/ETag。浏览器每次请求资源时,会携带上次服务器响应的 ETag/Last-Modified 作为标志,与服务端此时的 ETag/Last-Modified 作比较,来判断内容更改。

HTTP 缓存_缓存_07

关注「前端加加」, 第一时间获取优质文章.