Skip to content

浏览器缓存机制

    1. 浏览器在发送请求前先判断是否命中强缓存
    • 命中则不发送请求直接使用缓存,否则进行下一步
    1. 浏览器发送请求后会由服务器判断是否命中协商缓存
    • 命中则从缓存获取资源,否则进行下一步
    1. 浏览器直接使用服务器返回的资源并更新缓存

强缓存(200 OK)

  • Expires 是服务器告诉浏览器的缓存过期时间(值为 GMT 时间,即格林尼治时间)
    • HTTP1.0 的产物
    • 受本地时间影响
    • 设置的值为 max-age=xxx(xxx 是 秒)
  • Cache-Control 用于控制缓存的行为
    • HTTP1.1 的产物
    • 取值
      • public:允许被客户端和代理服务器缓存
      • private:只允许被客户端缓存(默认值)
      • no-cache:允许被客户端和代理服务器缓存,但在使用缓存时需要经过协商缓存来验证决定
      • no-store:所有内容都不会被缓存,即不使用强制缓存也不使用协商缓存每次请求都会下载完整的资源
      • maxage=xxx:设置客户端和代理服务器的缓存时间,表示缓存内容将在 xxx 秒后失效
      • s-maxage=xxx:设置代理服务器的缓存时间(优先级比 max-age 高)

Cache-Control 注意点

no-cache 名字存在误导,其并不是不缓存数据,只是在使用缓存时需要经过协商缓存来验证决定
max-age=0no-cache 效果一致

缓存位置

  • 内存缓存(memory cache)
    • 快速读取(内存缓存将编译解析后的文件,直接存入该进程的内存中,占据该进程一定的内存资源,以方便下次运行使用时的快速读取)
    • 进程关闭时数据会被清除
    • 不请求网络资源,资源存在内存中一般 JS 和图片文件会存入内存
    • 状态码:200(from memory cache)
  • 硬盘缓存(disk cache)
    • 写入硬盘文件进行 I/O 操作
    • 进程关闭时数据不会被清除
    • 速度比 memory cache
    • 不请求网络资源,资源存在磁盘中一般非脚本会存在磁盘中,如 css
    • 状态码:200(from disk cache)
  • 代理服务器缓存(server worker)
    • 可以拦截处理页面的所有网络请求
    • HTTPS 下可用、存在兼容问题
    • 状态码:200(from service worker)

协商缓存(304 Not Modified)

Last-ModifiedIf-Modified-Since

Last-Modified 表示资源的最后修改时间,值为 GMT 格式时间字符串,精确到秒

  • 浏览器第一次请求时,服务器会在响应头中返回请求资源的上次更新时间 Last-Modified
  • 当浏览器再次请求时,会在请求头中携带 If-Modified-Since 值为上次请求返回的 Last-Modified
  • 服务器收到请求后,会根据请求头中的 If-Modified-Since 和该资源在服务器的最后被修改时间做对比
    • 大于 If-Modified-Since 重新返回资源文件,状态码为 200
    • 小于 If-Modified-Since 资源无更新继续使用缓存文件,状态码为 304

Last-Modified 存在的问题

  • 时间精度为秒级会出现误差情况,对文件修改精度有严格要求的场景不能满足
  • 在集群服务器上各个服务器上的文件时间可能不同
  • 如果用旧文件覆盖新文件,因为时间更前浏览器不会请求旧文件
  • 编辑了文件但未修改,会导致缓存失效

ETag 和 If-None-Match

ETag 是服务器通过算法对资源内容计算出的一个唯一标识(文件 hash)其有强弱之分

  • Etag
    • ETag: "<etag_value>"
    • 资源发生任何改变都会立刻更新
    • 难生成,利于比较
  • Etag(使用 W/ 标识)
    • ETag: W/"<etag_value>"
    • 只在资源发生本质变化时更新
    • 易生成,不利于比较
过程
  • 浏览器第一次请求时,服务器会在响应头中返回当前资源文件的一个唯一标识 ETag
  • 当浏览器再次请求时,会在请求头中携带 If-None-Match 值为上次请求返回的 ETag
  • 通过接收的 ETag 和服务器重新生成的 ETag 进行对比
    • 不一致 重新返回资源文件,状态码为 200
    • 一致 资源无更新继续使用缓存文件,状态码为 304

Last-Modified 和 Etag 对比

  • 精确度上:Etag 优于 Last-Modified
  • 性能上:Etag < Last-Modified 每次生成 ETag 都需要进行读写操作,而 Last-Modified 只需要读取操作
  • 优先级:服务器校验优先考虑 Etag(先判断 Etag 是否变化,如果 Etag 没有变化再判断 Last-Modified

应用场景

强缓存协商缓存
不常变化的文件
带 hash 值的 css js 图片
频繁变动的文件
html 文件

用户行为对缓存的影响

  • 地址栏输入
    • 查找 disk cache(磁盘缓存)中是否有匹配,有则使用缓存,没有则发送网络请求
  • 普通刷新(F5)
    • 因为浏览器 tab 标签并没有关闭,因此 memory cache (内存缓存)是可用的,会被优先使用,其次使用 disk cache(磁盘缓存)
    • 跳过强缓存规则,直接走协商缓存
  • 强制刷新(Ctrl + F5)
    • 浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache (为了兼容还带了 Pragma: no-cache)服务器直接返回 200 和最新内容。
    • 跳过所有缓存规则