← 返回题目列表

浏览器强缓存和协商缓存有什么区别?

高频 中等 第 4 / 30 题 更新于 2026/07/28
浏览器HTTP缓存强缓存协商缓存

简化版

强缓存是在缓存未过期时直接使用本地资源,不请求服务器,主要由 Cache-ControlExpires 控制。协商缓存会向服务器验证资源是否变化,主要通过 ETag/If-None-MatchLast-Modified/If-Modified-Since,未变化返回 304。

详细版

强缓存命中时,浏览器不会发送请求,速度最快。现代项目主要使用 Cache-Control: max-age=... 控制缓存时长。

协商缓存会发送请求到服务器,服务器判断资源是否变化。如果没变化,返回 304,浏览器继续使用本地缓存;如果变化,返回新资源。

常用头:

  • 强缓存:Cache-ControlExpires
  • 协商缓存:ETagLast-Modified

工程中常见策略是:HTML 不强缓存或短缓存,带 hash 的静态资源长期强缓存。

完整版教学

一、强缓存

强缓存的特点是“不问服务器”。只要本地缓存还在有效期内,浏览器直接使用缓存资源。

Cache-Control 是 HTTP/1.1 的缓存控制头,优先级高于 Expires。常见配置:

Cache-Control: public, max-age=31536000, immutable

适合文件名带内容 hash 的 JS、CSS、图片。只要内容变了,构建产物文件名也变,旧缓存不会影响新版本。

二、协商缓存

协商缓存的特点是“问一下服务器资源有没有变”。

ETag 是资源内容标识,浏览器下次请求带上 If-None-Match。服务器对比后,如果没变返回 304。

Last-Modified 是资源最后修改时间,浏览器下次带上 If-Modified-Since。它精度不如 ETag,也可能受服务器时间影响。

通常 ETag 优先级更高。

三、项目中的缓存策略

单页应用或静态站常用策略:

  • index.html:不强缓存或短缓存,保证能拿到最新资源引用。
  • app.[hash].js:长期强缓存。
  • style.[hash].css:长期强缓存。
  • 图片和字体:根据是否带 hash 设置缓存。

这样既能让静态资源缓存很久,又能通过 HTML 更新引用到新版本文件。

四、面试追问与工程落地

面试官可能问:“为什么 HTML 不能长期强缓存?”

因为 HTML 通常引用当前版本的 JS 和 CSS。如果 HTML 被长期缓存,用户可能一直加载旧资源入口,即使服务器已经发布新版本也看不到。

工程中还要注意 CDN 缓存刷新、灰度发布和回滚。如果资源文件名带 hash,回滚时旧资源仍可访问会更安全。

五、指令语义与缓存位置

no-cache 允许存储响应,但复用前必须向源站验证;no-store 才表示缓存不应存储。max-age=0 表示响应立即变旧,通常也会触发验证。把三者都解释成“禁用缓存”是高频错误。

指令可否存储再次使用前是否验证常见用途
max-age=31536000, immutable可以新鲜期内通常不验证内容 hash 静态资源
no-cache可以每次复用前验证需要始终确认最新的 HTML
no-store不应存储无缓存可复用高敏感且不应落缓存的响应
private私有缓存可以由其他指令决定个性化用户响应

缓存不只在浏览器,还可能经过 Service Worker、代理和 CDN。响应会因 Accept-EncodingOrigin 等请求头变化时,需要正确设置 Vary;否则 CDN 可能把一个变体错误复用给另一个用户,动态反射 CORS 来源时尤其要配 Vary: Origin

六、验证器、版本发布与数字推演

浏览器携带 If-None-Match,服务器若确认 ETag 未变化可返回 304,304 没有新的响应体但仍消耗一次网络往返。Last-Modified 的时间粒度和资源变化语义较弱,ETag 更灵活;两者同时存在时,客户端与服务器按 HTTP 验证规则处理,不能简单理解成“两个都必须命中”。

假设 JS 文件 800KB、RTT 100ms:强缓存命中几乎省掉 800KB 传输和验证 RTT;304 省掉响应体,但仍至少付出约 100ms 往返;200 则两者都付。带内容 hash 的资源可长缓存,HTML 使用 no-cache 配 ETag,让入口更新而旧 hash 文件继续可用。

首次:GET app.a1.js → 200 + body + max-age
新鲜期:本地直接复用
过期验证:If-None-Match: "a1" → 304
内容发布:HTML 引用 app.b2.js → 新 URL 获取 200

灰度与回滚要求旧 hash 资源保留一段时间,不能发布后立即删除。否则用户缓存的旧 HTML、正在加载的页面或 CDN 节点仍可能请求旧文件并得到 404。

缓存心法:URL 表示资源版本,Cache-Control 决定新鲜度,验证器回答内容是否变化,Vary 决定同一 URL 有哪些变体。

七、常见误区与追问

  • 误区:Cache-Control: no-cache 表示浏览器完全不缓存。 它允许存储,只要求复用前验证;完全不存储是 no-store
  • 误区:返回 304 就没有网络成本。 它省响应体,但 DNS/连接状态和至少一次请求往返仍可能产生耗时。
  • 误区:设置超长 max-age 后覆盖同名 JS 就能及时更新。 新鲜缓存不会询问服务器,应使用内容 hash 生成新 URL。
  • 追问:ETag 与 Last-Modified 如何选择? 静态资源可同时提供;ETag 表达更灵活,Last-Modified 成本低但时间精度与语义有限。
  • 追问:为什么个性化响应要关注 private 防止共享缓存把带用户数据的响应提供给其他用户。
  • 追问:Vary 解决什么问题? 它让缓存键包含指定请求头,避免语言、编码、来源等响应变体相互污染。
  • 追问:Service Worker 缓存和 HTTP 缓存一样吗? 不一样;前者由脚本策略控制请求与 Cache Storage,后者遵循 HTTP 缓存语义,两层可能同时存在。

八、加强记忆

缓存按“四件套”记:Cache-Control 管能否存和新鲜多久,ETag/Last-Modified 管过期后验证,内容 hash 管版本换 URL,Vary 管同一 URL 的响应变体。强缓存省请求,304 只省响应体;HTML 需要及时验证,hash 静态资源适合长期缓存,并为灰度与回滚保留旧文件。