浏览器缓存

把已请求并返回的 WEB 资源(HTML 页面、图片、JS 文件、CSS 文件、数据等)复制成一个副本存储在浏览器的缓存中

缓存好处

  1. 减少网络带宽的消耗
  2. 降低服务器压力
  3. 减少网络延迟

    缓存策略

    第一次必须获取到资源后,然后根据返回来的信息告诉如何缓存资源
  • 可能采用强缓存
  • 也可能告诉客户端浏览器是协商缓存

这是根据响应的 header 内容来决定。

浏览器第一次请求

浏览器后续再进行请求

强缓存 & 协商缓存

强缓存

利用 HTTP 请求头中 expirse 和 cache-control 两个字段来控制,用来表示资源的缓存时间
cache-control (HTTP1.1 出现的 header 信息)

  • no-cache 浏览器忽略资源缓存副本,强制到服务器获取资源(浏览器依然缓存)
  • no-store 强制缓存在任何情况下都不要保留任何副本
  • max-age=31536000 指示缓存副本的有效时长,从请求时间开始到过期时间之间的秒数
  • public 表明响应可以被任何对象(包括:发送请求客户端,代理服务器 等等)缓存
  • private 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)

expires (HTTP1.0 规范)
启用缓存和定义缓存时间。告诉浏览器资源缓存过期时间,如果还没有过该时间点则不发请求

  • 值为一个绝对时间的 GMT 格式的时间字符串,如
    • expires: Mon, 10 Jun 2015 21:31:12 GMT
  • 在 HTTP1.1 开始被,cache-control:max-age=秒 所替代
  • 如果 cache-control 与 expires 同时存在的话,cache-control 的优先级高于 expires

协商缓存

  • Etag 服务端资源唯一标识符(优先级高于 Last Modified)
    Entity tag 缩写,被请求变量的实体值,是服务器一个资源标识,在 HTTP 响应头中将其传送到浏览器。
    1. 如第一次请求时服务器返回 Etag:'50b1c1d4f775c61:df3' 给浏览器当浏览器再次请求这个资源时
    2. 浏览器再次请求这个资源时,会将 If-None-Match: '50b1c1d4f775c61:df3' 放在请求头
    3. 服务器拿到这个 Etag,会对比资源是否发生变化,如果未发生改变,则返回 304 HTTP 状态码,而不返回具体的资源
  • Last-Modified 资源在服务器最后的修改时间

    1. 在浏览器第一次请求时,服务器成功返回状态为200,内容是请求的资源,同时有一个 Last-Modified 的属性标记这资源在服务器最后被修改的时间,也是一个 GMT 格式的时间字符串 Last-Modified:Mon, 10 Jun 2015 21:31:12 GMT
    2. 浏览器再次请求这个资源时,会将 If-Modified-Since: Mon, 10 Jun 2015 21:31:12 GMT 放在请求头
    3. 服务器拿到 If-Modified-Since,会对比手上资源的最后修改时间,如果时间没有修改,则返回 304 HTTP 状态码,而不返回具体的资源

      既生 Last-Modified 何生 Etag

      Last-Modified 已经足以让浏览器知道本地缓存副本是否足够新,为什么在 HTTP1.1 还出现 Etag?
      Etag的出现是为了解决几个在 Last-Modified 比较难解决的问题:
  • 一些文件也许会周期性的更改,但是他的内容并不改变(即仅只改变修改时间),这个时候我们并不希望浏览器认为这个文件是被修改,而要重生下获取

  • 某些文件修改非常频繁,比如在 1 秒以内修改了 N 次,If-Modified-Since 能检查到的粒度只是秒级,这种修改无法判断
  • 某些服务器不能精确地得到文件最后的修改时间

所以利用 Etag 可以更加准确地控制缓存,因为 Etag 是服务器自动生成或由开发者生成的对应资源在服务器的唯一标识符。

Last-Modified 与 Etag 是可以一起使用,服务器会优先验证 Etag,一致的情况下,才会继续对比 Last-Modified,最后才决定是否返回 304