浏览器的 HTTP 缓存如何工作?
未标记
考查重点:缓存新鲜度与条件请求。新鲜副本直接复用;过期后携 ETag 等验证,未变返回304复用内容,变化则取新响应
本题目录
参考答案
核心回答
浏览器的 HTTP 缓存会保存可缓存的响应,后续访问时,先判断是否有匹配的副本,再判断能否直接复用,必要时向服务器验证。
- 没有可用副本:正常请求资源,服务器返回内容与缓存策略;浏览器按策略决定是否保存。
- 副本仍新鲜且允许直接复用:直接用本地内容,不为这次资源访问发送网络请求,通常称为“强缓存”。常见的新鲜度依据是
Cache-Control: max-age,也可以使用Expires。 - 副本需要验证:若有验证器,发送带
If-None-Match或If-Modified-Since的条件请求,通常称为“协商缓存”。未变化时返回 304,无需重传响应体,浏览器更新相应缓存元数据并复用原内容;变化时通常返回 200 和新内容。没有验证器时,不能凭空协商,通常需要重新获取内容。
两者的区别是:直接复用省掉这次网络请求,协商复用仍有网络往返,主要节省响应体传输。
新鲜度与验证器分别管什么?
max-age=600 表示响应的最大新鲜寿命为 600 秒,要结合响应当前的年龄判断。经过 CDN 等中间缓存时,还要考虑 Age,不能每到一个浏览器都重新获得完整的 600 秒。Expires 给出绝对过期时间;同时存在有效的 max-age 时,按 max-age 确定新鲜寿命。
新鲜度回答“现在可否不问服务器就用”,验证器回答“服务器上的表示是否还是同一版”:
ETag/If-None-Match:服务器给响应一个版本标识,客户端在校验时带回。ETag可以基于内容哈希或版本号生成,并不规定必须怎样计算。Last-Modified/If-Modified-Since:基于最后修改时间校验。它的时间精度和服务端记录方式可能限制判断能力,例如同一秒内多次变化。
两组条件头同时出现时,If-None-Match 优先,服务端忽略 If-Modified-Since,不是先比较 ETag,再把修改时间当第二道条件。
例如某 CSS 响应带 max-age=600 和 ETag: "v1":普通重复访问且仍新鲜时直接复用;需要验证时带 If-None-Match: "v1"。服务端确认仍是该表示就返回 304,否则返回新 CSS 和新的验证器。具体是否发请求,还会受刷新方式和请求的缓存指令影响。
Cache-Control 中几个容易混淆的值
no-cache:可以存储,但复用前需要成功验证。它不是“不保存”。no-store:要求缓存不要存储这次请求和响应,也不能用该响应满足后续请求;它不会自动清除此前已经保存的同 URL 副本。private:限制共享缓存存储,浏览器这类私有缓存仍可能保存;它不等于“不缓存”。public:明确允许共享缓存存储,不能随意用于个性化响应。must-revalidate:副本过期后,必须成功验证才能复用,不能因为离线或服务器出错就直接返回过期内容。
没有设置 Cache-Control 也不等于必定不缓存,某些响应可以按规则进行启发式缓存。实际项目应明确配置策略。
项目中怎么设置和排查?
对内容带哈希的静态资源,例如 app.a1b2c3.js,可以设置较长的新鲜期;内容变化就生成新 URL,并更新 HTML 引用。immutable 可以表达该 URL 的内容在新鲜期内不会变化。入口 HTML 则通常采用短新鲜期或 no-cache,让用户能够及时发现新资源。
用户相关响应要考虑私有性与更新要求,例如允许浏览器存储但每次验证,可以组合 private, no-cache;不希望被 HTTP 缓存保存的敏感响应可以用 no-store。账户切换等场景还要处理旧内容,不能只加一个 private 就认为完成了用户隔离。
排查时看开发者工具中的响应缓存头、请求条件头、是否来自 memory/disk cache,以及真实网络响应是否为 304。同时检查 URL 与 Vary:同一 URL 如果按语言返回不同内容,应通过 Vary: Accept-Language 等方式区分副本。发布后只修改源站文件或刷新 CDN,也不会主动让仍新鲜的浏览器副本失效。
这里讨论的是 HTTP 响应缓存;localStorage、应用内缓存、Service Worker Cache Storage 和页面前进后退缓存还有各自机制。协商缓存使用条件请求,不是 CORS 的 OPTIONS 预检。
参考资料
- 国内:JavaGuide:访问网页的全过程:采用“浏览器缓存检查”部分,把直接复用、发条件请求和真正获取新内容放进一次资源访问流程。
- 国内:小林coding:HTTP 常见面试题:采用强缓存与协商缓存部分,解释 Expires、Cache-Control、两组验证器和 304 的基本作用。
- 国内:阿里云:配置 CDN 缓存过期时间:采用生产环境中的版本化文件名和缓存时长取舍,说明为什么静态资源更新要配合新 URL,以及长缓存带来的更新延迟。
- 国外:MDN:HTTP caching:采用新鲜度、Age、验证器和重新加载部分,解释缓存年龄、ETag 的生成方式,以及 no-cache 与 no-store 的差别。
- 国外:IETF:RFC 9111 — HTTP Caching:采用缓存复用、Vary、条件验证和缓存指令规定,明确 If-None-Match 的优先级、304 元数据更新与私有/共享缓存边界。
相关面经
17 篇快手
浏览器缓存策略(说了协商缓存和商缓存,追问为什么最后修改时间不能区分是否变化)
字节跳动
前端开发工程师浏览器缓存策略
阿里巴巴
全栈开发请简单介绍一下 HTTP 强缓存、协商缓存,以及一次返回 304 的请求中发生了什么。
虚拟盒子
前端实习生浏览器缓存
腾讯
浏览器缓存?session storage和local storage的区别?
展开剩余 12 篇面经
字节跳动
前端开发工程师(Agent)展开讲讲浏览器缓存
华为
JavaScript 开发浏览器缓存策略
智元机器人
前端开发工程师浏览器缓存机制是什么?强缓存和协商缓存分别是什么?
虾皮
前端开发工程师http缓存机制、强缓存和协商缓存
美团、慧博、感易智能、融智通、点点互动、京东、乐信圣文
浏览器缓存,强缓存有什么缺点,为什么要有协商缓存
快手、金山云、蔚蓝云创、深势科技、滴滴
你有用到HTTP里面的缓存的机制吗
阿里巴巴
前端开发工程师了解浏览器的缓存机制吗
百度
AI应用开发前端资源缓存怎么配的?
引力波信息科技
前端开发浏览器缓存是什么




