转载:按 F5 刷新和在地址栏回车,浏览器的缓存策略到底有啥区别?
前言🔖
面试官问:”浏览器缓存策略有哪些?”
你熟练地背诵:”强缓存用 Cache-Control,协商缓存用 ETag 和 Last-Modified…”
面试官点点头,接着问:”那我在地址栏输入 URL 回车,和按 F5 刷新,这两种情况下,缓存策略生效有什么区别?”

这一问,把很多只背了 HTTP 头定义的候选人问住了。
“难道…不都是发请求吗?”
当然不是。用户行为会直接改变浏览器对缓存头的处理方式。 这篇文章就帮你把这个隐蔽的知识点挖透。
浏览器都会缓存网页吗? 会缓存网页的全部内容吗🔖
浏览器默认会缓存网页内容,但不会缓存全部内容,缓存的范围和规则由 HTTP 缓存头、浏览器策略、资源类型共同决定。
🔹浏览器是否都会缓存网页?
绝大多数现代浏览器(Chrome、Firefox、Edge、Safari 等)都支持网页缓存,这是浏览器提升加载速度、减少服务器压力的核心机制。
- 缓存是浏览器的默认行为,但可以通过代码(HTTP 响应头)、浏览器设置手动控制(比如设置 “禁止缓存”“无痕模式”)。
- 极少数特殊场景下缓存会被禁用:
- 网页通过
Cache-Control: no-store明确禁止缓存; - 浏览器开启无痕模式(缓存数据仅在会话期间存在,关闭窗口后自动清除);
- 浏览器缓存空间已满,会自动清理旧缓存。
- 网页通过
🔹浏览器会缓存网页的全部内容吗?
不会。浏览器会根据资源类型和缓存规则选择性缓存,核心分为两类:

🔹关键补充:缓存的核心控制规则
浏览器缓存的 “开关” 和 “有效期” 由后端返回的 HTTP 缓存响应头决定,常见的有:
Cache-Control:最核心的缓存控制头Cache-Control: max-age=3600:资源缓存 1 小时,1 小时内直接从本地读取;Cache-Control: no-cache:需要先和服务器验证资源是否过期,再决定是否使用缓存;Cache-Control: no-store:完全禁止缓存,每次都从服务器重新请求。
Expires:旧版缓存头,指定缓存过期时间(优先级低于Cache-Control)。
🔹关键补充:缓存的核心控制规则
浏览器缓存就像冰箱储存食物:
- 不会把超市所有食物都买回家(不会缓存全部网页内容);
- 优先储存耐放的食材(静态资源:CSS/JS/ 图片),短期储存生鲜(HTML 页面);
- 过期食材会扔掉重新买(缓存过期后重新请求),标注 “禁止储存” 的食材不会放进冰箱(
no-store资源)。
三种刷新操作,三套缓存逻辑🔖
为了搞清这个问题,我们不能只看服务器发了什么头,还得看用户怎么操作。浏览器把用户行为分成了三个等级:
🔹1. “最懒”模式:地址栏回车 / 点击链接 / 前进后退
当你在地址栏输入 URL 回车,或者点击页面跳转链接时,浏览器会表现得”非常懒”。
它会优先看本地有没有强缓存(Cache-Control: max-age=xxx)。
- 如果有,且没过期,根本不会向服务器发请求。
- 你会在 Network 面板看到状态码是
200 (from disk cache)或200 (from memory cache)。 - 只有强缓存失效了,才会发请求去问服务器(协商缓存)。
结论:这是最利用缓存的方式,也是用户最常见的行为。
🔹2. “怀疑”模式:按 F5 刷新 / 点击刷新按钮
当你按下 F5 时,浏览器的潜台词是:”我不信本地缓存是新的,我要去服务器问问。”
这时候,浏览器会无视强缓存(Cache-Control)的有效期。哪怕 max-age 还有 100 年,它也会强制发起 HTTP 请求。 但是!它还没彻底放弃治疗,它会带上 If-Modified-Since 或 If-None-Match 去问服务器:”这文件改了吗?”
- 如果服务器说没改(304 Not Modified),浏览器才去读本地缓存。
- 如果改了(200 OK),就下载新的。
结论:F5 会跳过强缓存判断,直接进行协商缓存。
🔹3. “暴力”模式:Ctrl + F5 (Mac: Cmd + Shift + R)
这是开发者的最爱:强制刷新。
浏览器的潜台词是:”把旧的都扔了,给我来份全新的!”
这时候,浏览器会做两件事:
- 删除/忽略本地所有的缓存文件。
- 在请求头里带上
Cache-Control: no-cache和Pragma: no-cache。
这相当于告诉服务器:”别给我 304,我不要旧的,给我 200 和最新内容。”
结论:完全绕过所有缓存机制,就像第一次访问一样。
还有一个坑:Memory Cache vs Disk Cache🔖
细心的同学在 Chrome Network 面板里会发现,同样是缓存,有时候显示 from memory cache,有时候显示 from disk cache。这又有啥区别?
面试官如果追问这个,多半是想考察你对浏览器进程模型的理解。
- Memory Cache(内存缓存):
- 快:读内存肯定快。
- 短:页面关了就没了。
- 场景:你刷新页面时,图片、脚本这些资源刚刚才加载过,大概率还在内存里,浏览器直接从内存拿,甚至都不用读硬盘。
- Disk Cache(硬盘缓存):
- 慢:比内存慢点,但在 SSD 时代也很快。
- 长:页面关了、浏览器关了都在。
- 场景:你昨天访问过的网站,今天再去访问,静态资源大概率是从硬盘里读出来的。
冷知识:浏览器通常会把小文件、频繁使用的文件扔内存;大文件、不常用的扔硬盘。但这完全由浏览器内核控制,开发者干预不了。
最佳实践:怎么让用户永远不按 Ctrl + F5?🔖
作为开发者,我们的终极目标是:既要缓存时间够长(省流量),又要更新够快(不发版事故)。
既然 F5 和回车的行为不可控,我们就得从文件名下手。
目前前端工程化(Webpack/Vite)的标准解法是:Content Hash。
- 文件名带指纹:
app.a1b2c3d4.js。 - HTML 不缓存:入口
index.html设置Cache-Control: no-cache,每次都去服务器拿最新的 HTML。 - JS/CSS 强缓存拉满:
app.a1b2c3d4.js设置Cache-Control: max-age=31536000(一年)。
效果:
- 只要你没改代码,Hash 不变,文件名不变。用户回车访问,直接走强缓存(200 from cache),速度飞快。
- 一旦你发版,Hash 变了,
index.html引用了新的app.e5f6g7h8.js。浏览器一看:”哟,新文件,没缓存过”,立刻请求新的。
这样,用户根本不需要关心是回车还是 F5,永远能看到最新代码,同时享受最强缓存。
面试怎么答?🔖
简洁版(30 秒):
浏览器对缓存的处理会根据用户行为降级。
正常访问(回车/链接)最优先使用强缓存,有效就不发请求。 F5 刷新会跳过强缓存,强制发起请求进行协商缓存(检查 ETag/Last-Modified)。 Ctrl+F5 强制刷新则是完全绕过所有缓存,请求头带 no-cache,直接向服务器要最新资源。
进阶版(1 分钟,带原理):
这本质上是浏览器在请求头里加了不同的指令。
正常访问时,浏览器查找 Disk/Memory Cache,命中强缓存则拦截请求。
当用户按 F5,浏览器会在请求头加 Cache-Control: max-age=0,这就导致强缓存失效,迫使服务器进行协商缓存验证(304 判断)。
而 Ctrl+F5 更暴力,它会加 Cache-Control: no-cache 和 Pragma: no-cache,不仅不读本地缓存,还暗示中间代理服务器(如 CDN)也别给旧货,必须回源拿最新的。
所以在实际项目中,我们不能依赖用户的刷新行为,而是应该用 HTML 协商缓存 + 静态资源 Hash 文件名 + 强缓存 的组合拳,来保证更新和性能的平衡。