浏览器缓存


1. 浏览器缓存简介

1.1 什么是浏览器缓存

浏览器缓存是指: 将从服务器获取的一些数据缓存到本地, 从而使得浏览器需要再次加载此数据时, 直接从计算机本地获取数据, 而不是通过服务器获取数据

1.2 为什么要有浏览器缓存

  1. 能够提高用户的体验: 从本地获取资源的速度一般情况下比从服务器获取资源的速度要快几个量级
  2. 能够缓解服务器的压力以及网络压力: 从本地获取资源这一行为并不需要向服务器请求资源(除非本地缓存过期了), 服务器也不需要占用对应量的带宽将数据传输回来

1.3 浏览器缓存资源的位置

  1. Memory Cache: 将资源缓存到内存中, 能够缓存的量相对 Disk Cache 来说较少, 获取资源的速度快于 Disk Cache, 但是关闭对应 Tab 后, 资源不会保存在内存中, 再次开启对应页面时不能从内存中获取到相应资源
  2. Disk Cache: 将资源缓存到硬盘中, 能够缓存的量相对 Memory Cache 来说更多, 获取资源的速度慢于 Memory Cache, 但是关闭对应 Tab 后, 资源仍存在于硬盘中, 再次开启对应页面仍能获取缓存

对于缓存位置:

  • 较大的文件, 其会优先放到硬盘中, 反之, 较小的文件会优先放到内存中
  • 如果内存使用率比较低, 就会优先将资源放到内存, 反之, 就会优先将资源放到硬盘

2. 浏览器缓存的类型

2.1 强缓存(强制缓存)

根据请求资源所对应的响应头的 cache-control(HTTP/1.1) 和 expires(HTTP/1.0) 字段来进行设置

2.1.1 cache-control

  • no-cache: 表示不设置强缓存, 但是仍可设置协商缓存
  • no-store: 表示不设置缓存(包括强缓存和协商缓存)
  • max-age=233: 表示该缓存在 233 秒后过期, 在此期间, 可以从缓存中获取该资源
  • private: 表示该资源只能在客户端被缓存, 不能被代理服务器缓存
  • public: 表示该资源可以被客户端和代理服务器缓存

2.1.2 expires

  • Mon, 01 Nov 2021 03:24:05 GMT: 表示该资源在格林威治时间 2021年11月01日03:24:05 时过期, 在此之前, 可以从缓存中获取该资源
    • 局限(为什么要使用 cache-control): 受限于本地时间, 如果本地时间和服务器的时间不相符, 则缓存可能达不到服务器所预想的效果

浏览器在请求服务器资源之前, 会先看看强缓存中是否有该资源(一般非 HTML 文件都会被强缓存), 且没有过期

  • 若存在该资源, 且没有过期: 则返回状态码 200 和该资源
  • 若不存在该资源, 或过期了: 启用协商缓存

2.2 协商缓存(强缓存不命中时启用)

根据请求资源所对应的响应头的 etag/if-none-match(HTTP/1.1) 和 last-modified/if-modify-since(HTTP/1.0) 字段来进行设置

2.2.1 etag/if-none-match

服务器响应时, 返回当前资源的一个唯一标识 etag(由服务器生成), 而浏览器则在缓存资源的同时记录 etag 的值.

  • 当需要从协商缓存中获取该资源时, 浏览器将记录的 etag 值作为 if-none-match 字段的值加入 requset header 中, 并发送给服务器
    • 若发送的 if-none-match 与服务器中资源对应的标识相同, 则说明服务器的资源与客户端协商缓存的资源相同, 服务器返回 304 表示资源没有被修改. 客户端收到响应, 直接使用本地资源
    • 否则, 服务器重新发送资源给客户端, 客户端重新缓存该资源

2.2.2 last-modified/if-modify-since

last-modified 的格式与 expires 的格式一样, 都是一个时间, 只不过这个时间指的是对应资源最后一次更新的时间

  • 当浏览器请求对应资源时, request header 中会包含 if-modify-since, 其值为 last-modified, 服务器收到 request 之后, 通过检查 if-modify-since 来判断是否需要重发资源
    • 若不需要重发资源, 则直接发送一个 304 状态码, 客户端继续使用缓存的资源
    • 否则, 服务器重新发送资源给客户端, 客户端重新缓存该资源
  • 局限(为什么要使用 etag/if-none-match):
    • last-modified 只能精确到秒, 如果一个资源在 1s 内发生了变化, 服务器就会判断出错, 从而导致浏览器使用错误的资源
    • 如果某个资源的内容没有发生改变, 但是它的修改时间又发生了变化, 那么服务器也会重新发送该资源