HTTP缓存 – 强缓存/协商缓存/浏览器刷新

12次阅读

共计 2363 个字符,预计需要花费 6 分钟才能阅读完成。

Web 缓存:

数据库缓存、服务器端缓存(代理服务器缓存、CDN 缓存)、浏览器缓存

浏览器缓存:

HTTP 缓存、indexDB、cookie、localstorage 等等

HTTP 缓存

  • 强制缓存的优先级高于协商缓存
  • 强缓存: 命中缓存不需要和服务器端发生交互
  • 协商缓存: 不管是否命中都要和服务器端发生交互
  • 流程:

强缓存

  • Expires

    • 定义:缓存过期的时间,超过了这个时间点就代表资源过期
    • 缺点:服务器时间,客户端时间可随意修改
    • HTTP/1.0 的标准
  • Cache-Control

    • 由多个字段组合而成

      • max-age 指定一个时间长度,在这个时间段内缓存是有效的,单位是 s(相对时间)
      • no-store 禁止缓存,每次请求都要向服务器重新获取数据
      • no-cache : max-age = 0 仍然缓存,但是走协商缓存
      • public 表明响应可以被任何对象(发送请求的客户端、代理服务器等等)Public 设置我们可以将 Http 响应数据存储到本地,但此时并不意味着后续浏览器会直接从缓存中读取数据并使用 - 无法确定本地缓存的数据是否可用(可能已经失效)需要配合使用
      • private 表明响应只能被单个用户(可能是操作系统用户、浏览器用户)缓存,是非共享的,不能被代理服务器缓存
    • 缓存数据标记为已过期只是告诉客户端不能再直接从本地读取缓存了,还可能被再次用到(协商缓存)
    • cache-control 使用

  • Cache-Control 的优先级更高,覆盖 expire

协商缓存

浏览器第一次请求数据之后会将数据和响应头部的缓存标识存储起来。再次请求时会带上存储的头部字段,服务器端验证是否可用。如果返回 304 Not Modified,代表资源没有发生改变可以使用缓存的数据,获取新的过期时间。反之返回 200 就相当于重新请求了一遍资源并替换旧资源

  • Last-modified(响应头)/If-Modified-Since(请求头)

    • 服务器端收到带 If-Modified-Since 的请求后会去和资源的最后修改时间对比。若修改过就返回最新资源,状态码 200,若没有修改过则返回 304
    • 注意:Last-modified 要记得配合 Expires/Cache-Control 使用,不设置,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样 ( 根据响应头中 2 个时间字段 Date 和 Last-Modified 之间的时间差值,取其值的 10% 作为缓存时间周期。)
  • Etag/If-None-Match

    • 由服务器端上生成的一段 hash 字符串,第一次请求时响应头带上 ETag: abcd,之后的请求中带上 If-None-Match: abcd,服务器检查 ETag,返回 304 或 200
    • last-modified 和 Etag 区别

      • 某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新。
      • Last-modified 只能精确到秒。
      • 一些资源的最后修改时间改变了,但是内容没改变,使用 Last-modified 看不出内容没有改变。
      • Etag 的精度比 Last-modified 高,属于强验证,要求资源字节级别的一致,优先级高。如果服务器端有提供 ETag 的话,必须先对 ETag 进行 Conditional Request

实际使用

考虑缓存的内容:
  • css 样式文件
  • js 文件
  • logo、图标
  • html 文件
  • 可以下载的内容
一些不应该被缓存的内容:
  • 业务敏感的 GET 请求
不经常改变的文件
  • 给 max-age 设置一个较大的值,一般设置 max-age=31536000(一年)
  • 文件名称添加版本号、hash 值
可能经常需要变动的文件:
  • Cache-Control: no-cache / max-age=0

浏览器几种刷新方式对缓存的影响

1、在 URI 输入栏中输入然后回车

200 OK (from cache),浏览器发现该资源已经缓存了而且没有过期(通过 Expires 头部或者 Cache-Control 头部),没有跟服务器确认,而是直接使用了浏览器缓存的内容。其中响应内容和之前的响应内容一模一样

2、F5/ 点击工具栏中的刷新按钮 / 右键菜单重新加载

无论如何都发一个 HTTP Request 给 Server,即使先前的响应中有 Expires 头部

Cache-Control: max-age=0 // Chrome 强制加上的
If-Modified-Since: Fri, 15 Jul 2016 04:11:51 GMT

3、Ctl+F5

彻底的从 Server 拿一份新的资源过来

还需要添加一些 HTTP Headers。按照 HTTP/1.1 协议,Cache 不光只是存在 Browser 终端,从 Browser 到 Server 之间的中间节点 (比如 Proxy) 也可能扮演 Cache 的作用
在 Chrome 51 中会包含两个头部信息,作用就是让中间的 Cache 对这个请求失效,这样返回的绝对是新鲜的资源。

Cache-Control: no-cache
Pragma: no-cache
Cache-Control: no-cache

总结

  • 四种缓存的优先级:cache-control > expires > etag > last-modified**
  • cache-control:设置过期的时间长度(秒),在这个时间范围内,浏览器请求都会直接读缓存
  • expires:在 http 头中设置一个过期时间,在这个过期时间之前,浏览器的请求都不会发出,而是自动从缓存中读取文件,除非缓存被清空,或者强制刷新
  • etag / if-none-match: 服务器端返回资源时,如果头部带上了 etag,那么资源下次请求时就会把值加入到请求头 if-none-match
  • last-modified / if-modified-since: 服务器端返回资源时,如果头部带上了 last-modified,那么资源下次请求时就会把值加入到请求头 if-modified-since

正文完
 0