强缓存和协商缓存的使用

秋招之前本人不想再做强缓存和协商缓存的笔记了,已经写了四五遍了,真的很头疼我这坏习惯。都是因为我记笔记太混乱了,每次都找不到自己记得笔记,然后就只能能重新再记一遍。

一、先搞懂「强缓存优先」的核心逻辑

强缓存和协商缓存是 HTTP 缓存的两个层级 ,浏览器会按「先查强缓存 → 强缓存失效再查协商缓存」的顺序判断,「优先」就是指:

只要强缓存的条件满足(比如资源还在 max-age 有效期内),浏览器连请求都不会发给服务器,直接从本地缓存取;只有强缓存过期了,才会发请求走协商缓存流程。

二、强缓存和协商缓存「不是必须同时配置」,可只配一种

1. 只配强缓存(最常见)
  • 配置方式 :只设置 Cache-Control(推荐)或 Expires,比如:

    http 复制代码
    Cache-Control: max-age=86400  // 缓存1天
  • 适用场景:静态资源(如图片、字体、不常更新的 JS/CSS),这类资源更新频率低,优先减少请求数。

  • 缺点:强缓存有效期内,就算服务器资源更新了,浏览器也拿不到新资源(除非用户手动清缓存/刷新)。

2. 只配协商缓存
  • 配置方式 :不设置 Cache-Control: max-age,只返回 Last-Modified + ETag,比如:

    http 复制代码
    Last-Modified: Tue, 28 Nov 2025 10:00:00 GMT
    ETag: "abc123"
  • 适用场景:资源更新频率高(如首页接口数据),需要每次确认服务器资源是否最新,但又想减少重复传输。

  • 缺点:每次都要发请求到服务器(只是命中时返回 304,不传输正文),比强缓存多了网络往返。

3. 同时配置(最优解,实际项目主流)
  • 配置示例

    http 复制代码
    Cache-Control: max-age=3600  // 先强缓存1小时
    Last-Modified: Tue, 28 Nov 2025 10:00:00 GMT
    ETag: "abc123"
  • 逻辑 :1小时内直接读本地缓存(强缓存);1小时后发请求,服务器对比 Last-Modified/ETag,没更新就返回 304(协商缓存),更新了才返回新资源。

  • 优势:兼顾「少请求(强缓存)」和「资源新鲜(协商缓存)」,是前端性能优化的常规操作。

三、面试速记结论

  1. 强缓存优先 = 浏览器先判断强缓存是否生效,生效则无请求,失效才走协商缓存;
  2. 可只配一种:
    • 只强缓存:适合静态、低频更新资源,省请求但更新不及时;
    • 只协商缓存:适合高频更新资源,保证新鲜但每次发请求;
  3. 实际项目建议「强缓存+协商缓存」搭配,平衡性能和时效性。

强缓存和协商缓存都使用的请求判断流程:

强缓存 + 协商缓存 组合使用的完整请求流程

结合 Cache-Control: max-age(强缓存) + ETag/Last-Modified(协商缓存) 的配置,浏览器的请求流程分为 首次请求强缓存有效期内请求强缓存过期后请求 三个阶段,以下是带细节的流程图解:


前置配置(服务器响应头)

http 复制代码
# 强缓存:资源缓存1小时(3600秒)
Cache-Control: max-age=3600
# 协商缓存:文件唯一标识 + 最后修改时间
ETag: "abc123456"
Last-Modified: Wed, 27 Dec 2025 10:00:00 GMT

完整流程(分阶段)

阶段1:浏览器首次请求该资源

  1. 浏览器发送 完整请求 到服务器(无缓存,不携带任何缓存相关请求头)。
  2. 服务器处理请求,返回 200 OK ,同时在响应头带上 Cache-Control + ETag + Last-Modified
  3. 浏览器接收响应:
    • 保存资源到本地缓存;
    • 记录缓存元信息(max-age 过期时间、ETagLast-Modified)。
  4. 浏览器渲染资源。

阶段2:强缓存有效期内(1小时内)再次请求

  1. 浏览器检查缓存元信息:max-age 未过期 → 强缓存生效
  2. 浏览器 不发送任何请求到服务器,直接从本地缓存读取资源。
  3. 控制台 Network 面板显示:200 OK (from disk cache/memory cache)
  4. 渲染资源(全程无网络请求)。

阶段3:强缓存过期后(1小时后)再次请求

  1. 浏览器检查缓存元信息:max-age 已过期 → 强缓存失效,进入协商缓存流程

  2. 浏览器自动在 请求头携带缓存验证字段

    http 复制代码
    # 对应 ETag 的验证字段
    If-None-Match: "abc123456"
    # 对应 Last-Modified 的验证字段
    If-Modified-Since: Wed, 27 Dec 2025 10:00:00 GMT
  3. 服务器接收请求,对比验证字段:

    • 情况A:资源未更新 (ETag/Last-Modified 一致)
      • 服务器返回 304 Not Modified,响应体为空(节省带宽);
      • 浏览器更新本地缓存的 max-age 过期时间(重新开始计时);
      • 浏览器从本地缓存读取资源并渲染。
    • 情况B:资源已更新 (ETag/Last-Modified 不一致)
      • 服务器返回 200 OK ,带上新资源 + 新的 ETag + 新的 Last-Modified
      • 浏览器覆盖本地旧缓存,记录新的缓存元信息;
      • 浏览器渲染新资源。

流程总结图(文字版)

复制代码
首次请求
浏览器 →(无缓存头请求)→ 服务器 →(200+Cache-Control+ETag+Last-Modified)→ 浏览器 → 缓存+渲染

强缓存有效期内请求
浏览器 → 检查max-age未过期 → 直接读本地缓存 → 渲染(无请求)

强缓存过期后请求
浏览器 → 检查max-age过期 → 带If-None-Match/If-Modified-Since请求 → 服务器
    ↙️ 资源未更新(304) ↘️ 资源已更新(200+新缓存头)
浏览器更新缓存有效期    浏览器覆盖旧缓存
    ↘️                     ↙️
              读取缓存/新资源 → 渲染

面试关键要点

  1. 强缓存生效时 无请求 ,协商缓存无论命中与否 都有请求(304 无响应体,传输更快)。
  2. 协商缓存的请求头是浏览器 自动携带 的,无需前端手动设置。
  3. ETag 优先级高于 Last-Modified(解决文件修改时间秒级内变更的问题)。

需要我帮你整理缓存相关的面试易错点 吗?比如 no-cacheno-store 的区别、用户刷新对缓存的影响。(。。。)

相关推荐
此生只爱蛋2 小时前
【Redis】Zset 有序集合
数据库·redis·缓存
星辰_mya2 小时前
redis数据丢失之脑裂
数据库·redis·缓存
Psycho_MrZhang12 小时前
Redis 设计思想总结
数据库·redis·缓存
张彦峰ZYF16 小时前
高并发场景下的缓存雪崩探析与应对策略
redis·分布式·缓存
全栈工程师修炼指南19 小时前
Nginx | HTTP 反向代理:对上游服务端响应缓存流程浅析与配置实践
运维·网络协议·nginx·http·缓存
张彦峰ZYF21 小时前
高并发场景下的大 Key 问题及应对策略
redis·分布式·缓存
张彦峰ZYF21 小时前
高并发场景下的缓存击穿问题探析与应对策略
redis·分布式·缓存
Li_76953221 小时前
Redis进阶(二)—— Redis 事务
数据库·redis·缓存
极客小云1 天前
【Dockerfile 编写最佳实践:优化镜像构建与层缓存】
缓存·docker·k8s