浏览器缓存机制

核心说明:本文采用「通俗解读+专业知识点」结合模式,结构清晰、重点突出,可直接背诵用于面试;重点聚焦面试高频考点(强缓存、协商缓存),简化次要内容,补充面试答题技巧和常考问题,助力快速掌握核心。

一、浏览器缓存整体结构(面试开篇必背)

通俗说:浏览器缓存就是"本地仓库",访问网站时,能直接从本地拿资源就不麻烦服务器,既省时间又省流量。专业定义:浏览器对已请求过的资源进行本地存储,后续请求时优先复用本地资源,提升加载速度、降低服务器压力。

浏览器缓存主要分为三大类,面试重点考察前两类(合称HTTP缓存):

  • 1️⃣ 强缓存:最"懒"的缓存,完全不跟服务器打招呼,直接用本地缓存

  • 2️⃣ 协商缓存:比较"谨慎",会跟服务器打个招呼,由服务器决定要不要用缓存

  • 3️⃣ Service Worker 缓存:可编程缓存(面试非重点,简单了解即可,是前端进阶的缓存方式)

二、强缓存(Strong Cache)------ 面试高频重点

✅ 核心特点(必背)

通俗说:浏览器检查本地缓存,发现"没过期",就直接拿来用,根本不向服务器发请求。

专业表述:不发送HTTP请求,直接读取本地缓存资源;浏览器判断标准为「资源未过期」,此时Network面板显示状态码 200 (from disk/memory cache)(disk cache是硬盘缓存,memory cache是内存缓存,无需区分,面试提一句即可)。

1️⃣ 强缓存控制字段(核心考点)

(1)Cache-Control(优先级最高,面试重点)

通俗说:服务器给资源设定一个"保质期",浏览器在保质期内直接用缓存,过期了再找服务器。

专业示例(HTTP响应头):

http 复制代码
Cache-Control: max-age=3600

解读:表示该资源从请求成功开始,3600秒(1小时)内有效,期间再次请求无需访问服务器。

常见指令(必背,面试常考区别):

指令 通俗解读 专业作用
max-age=3600 资源保质期3600秒 指定资源的缓存有效时间(单位:秒)
no-cache 不偷懒,每次都问服务器 不使用强缓存,直接进入协商缓存流程
no-store 不存本地,每次都重新下载 完全不缓存资源,每次请求都需从服务器获取完整资源
public 谁都能存(浏览器、CDN等) 允许任何缓存节点(浏览器、代理服务器等)缓存该资源
private 只有浏览器能存 仅允许浏览器本地缓存,禁止代理服务器等中间节点缓存

(2)Expires(老版本,面试了解即可)

通俗说:服务器给资源设定一个"过期时间点",比如"2026年10月21日过期",浏览器对比本地时间,没到点就用缓存。

专业示例(HTTP响应头):

http 复制代码
Expires: Wed, 21 Oct 2026 07:28:00 GMT

核心缺点:依赖客户端(浏览器)本地时间,如果用户修改本地时间,会导致缓存判断失效(比如把时间改成过期后,缓存直接失效)。

⚠️ 优先级说明(必背):如果Cache-Control和Expires同时存在,Cache-Control 优先级 > Expires(因为Expires的缺陷太明显,现在基本用Cache-Control)。

📌 强缓存流程图(面试口述必背)

  1. 第一次请求:浏览器向服务器发送请求,服务器返回资源 + 强缓存控制字段(如Cache-Control: max-age=3600)

  2. 第二次请求(1小时内,未过期):浏览器检查本地缓存,发现资源未过期

  3. 直接从本地缓存读取资源,不向服务器发送任何请求

🎯 面试示例(帮助理解,可背诵)

场景:你的网站有一个脚本文件 <script src="app.js"></script>,服务器返回的响应头包含 Cache-Control: max-age=600(10分钟)。

结果:10分钟内刷新页面,Network面板会显示 app.js 的状态为 from memory cache,且没有任何HTTP请求发送到服务器。

三、协商缓存(Conditional Cache)------ 面试高频重点

✅ 核心特点(必背)

通俗说:强缓存过期了,浏览器不确定资源有没有更新,就向服务器"请示",由服务器判断要不要用本地缓存。

专业表述:浏览器会发送HTTP请求到服务器,服务器对比资源状态,决定是否复用本地缓存;若资源未变化,服务器返回状态码 304 Not Modified(不返回资源内容,只返回响应头);若资源已变化,返回200 + 新资源。

协商缓存的两种实现方式(必背,面试常考对比)

1️⃣ Last-Modified + If-Modified-Since(基于时间的判断,较老旧)

通俗说:服务器记录资源最后修改时间,浏览器下次请求时,带上这个时间,服务器对比"现在的修改时间"和"浏览器带的时间",判断资源有没有变。

  1. 第一次请求:服务器返回资源,并在响应头中添加 Last-Modified(资源最后修改时间),示例: Last-Modified: Wed, 01 Mar 2026 10:00:00 GMT

  2. 第二次请求:浏览器读取本地缓存中的 Last-Modified,在请求头中添加 If-Modified-Since(带上上次的修改时间),示例: If-Modified-Since: Wed, 01 Mar 2026 10:00:00 GMT

  3. 服务器判断:

    • 资源未修改(当前修改时间 = If-Modified-Since)→ 返回 304,浏览器用本地缓存

    • 资源已修改(当前修改时间 > If-Modified-Since)→ 返回 200 + 新资源 + 新的 Last-Modified

❌ 缺点(必背,面试常考)
  • 时间精度低:只能精确到秒,若1秒内资源被修改多次,服务器无法识别

  • 误判风险:文件修改但内容未变(如修改文件名再改回),服务器会认为资源已修改,返回新资源(浪费流量)

2️⃣ ETag + If-None-Match(基于内容的判断,更精准,面试重点)

通俗说:服务器给资源生成一个"内容指纹"(比如根据文件内容计算的一串字符),浏览器下次请求时带上这个指纹,服务器对比当前资源的指纹和浏览器带的指纹,判断内容有没有变。

  1. 第一次请求:服务器返回资源,并在响应头中添加 ETag(资源内容指纹),示例: ETag: "abc123"

  2. 第二次请求:浏览器读取本地缓存中的 ETag,在请求头中添加 If-None-Match(带上上次的指纹),示例: If-None-Match: "abc123"

  3. 服务器判断:

    • 指纹一致(资源内容未变)→ 返回 304,浏览器用本地缓存

    • 指纹不一致(资源内容已变)→ 返回 200 + 新资源 + 新的 ETag

📌 优先级(必背)

ETag > Last-Modified(因为ETag基于内容判断,更精准,能解决Last-Modified的缺点)。

四、强缓存 vs 协商缓存(面试必背对比,建议默写)

对比维度 强缓存 协商缓存
是否发送HTTP请求 ❌ 不发送 ✅ 发送(仅验证,不传递资源内容)
返回状态码 200 (from disk/memory cache) 304(未修改)/ 200(已修改)
服务器是否参与判断 否(浏览器自主判断) 是(服务器判断资源状态)
性能 更好(无需请求服务器) 次之(需发送请求,无需传输资源)

五、完整缓存流程(面试必会,口述核心)

浏览器请求资源时,判断顺序如下(必背,面试口述要流畅):

  1. 1️⃣ 先判断是否有强缓存:

    • 有强缓存,且资源未过期 → 直接读取本地缓存,不发送请求

    • 有强缓存,但资源已过期 → 进入协商缓存流程

  2. 2️⃣ 再判断是否有协商缓存标识(Last-Modified/ETag):

    • 有标识 → 发送请求到服务器,验证资源是否变化

    • 资源未修改 → 服务器返回304,浏览器用本地缓存

    • 资源已修改 → 服务器返回200 + 新资源,更新本地缓存

  3. 3️⃣ 既没有强缓存,也没有协商缓存 → 正常发送请求,服务器返回200 + 资源,同时设置缓存标识(强/协商)

六、真实场景应用(面试加分项,必背)

🎯 场景1:JS/CSS等静态文件更新了,如何保证用户拿到新版本?

通俗说:给静态文件名加"指纹"(hash值),比如 app.js 改成 app.1a2b3c.js,这样更新后文件名变了,浏览器会认为是新资源,重新下载。

专业表述:采用「缓存破坏(Cache Busting)」策略,具体操作:

  • 给静态资源(JS、CSS、图片)文件名添加hash后缀(如app.[hash].js)

  • 给静态资源设置强缓存,max-age=31536000(一年,因为文件名变了才会更新,不用担心过期)

  • 资源更新时,hash值会变化,文件名随之改变,浏览器会识别为新资源,重新请求下载

🎯 场景2:用户强制刷新页面,缓存会发生什么变化?(面试常考)

  • 普通刷新(点击刷新按钮/按F5):正常走缓存逻辑(先强缓存,再协商缓存)

  • 强制刷新(Ctrl + F5):跳过强缓存,直接进入协商缓存(相当于给请求头添加 Cache-Control: no-cache)

  • DevTools勾选 Disable cache:完全不使用任何缓存,每次请求都从服务器获取新资源

七、面试高频问题(必背,直接记答案)

❓1. 为什么需要协商缓存?

核心答案:强缓存过期后,资源可能并没有发生变化,如果直接重新下载会浪费流量和时间;协商缓存可以通过服务器验证资源状态,未变化则复用本地缓存,既保证资源新鲜,又提升性能、节省带宽。

❓2. 304状态码会返回资源内容吗?为什么?

核心答案:不会。因为304是"资源未修改"的响应,服务器只需告诉浏览器"可以用本地缓存"即可,无需返回资源内容,这样能减少网络传输量,提升加载速度。

❓3. 强缓存一般设置多久?不同资源有区别吗?

核心答案:有区别,分资源类型设置:

  • HTML文件:不设置强缓存,或设置协商缓存(因为HTML是入口文件,若强缓存,会导致引用的静态资源更新后,用户仍读取旧HTML,无法获取新版本)

  • 静态资源(JS、CSS、图片,带hash):设置1年(max-age=31536000),因为文件名带hash,更新时会自动触发缓存更新,无需担心过期问题。

❓4. 为什么HTML文件不能设置强缓存?(延伸题,必背)

核心答案:HTML是页面入口文件,负责引用JS、CSS等静态资源。如果给HTML设置强缓存,当静态资源更新(文件名变了),但HTML仍处于强缓存有效期内,浏览器会直接读取旧HTML,引用的还是旧的静态资源路径,导致用户无法看到新版本的页面。

❓5. no-cache 和 no-store 的区别?(高频易错,必背)

核心答案:两者都禁止强缓存,但对协商缓存和本地存储的处理不同:

  • no-cache:允许本地缓存,但不允许直接使用强缓存,必须发送请求到服务器进行协商缓存验证,验证通过后才能使用本地缓存。

  • no-store:完全禁止本地缓存,不允许浏览器存储任何资源,每次请求都必须从服务器获取完整资源,不存在缓存复用。

❓6. 浏览器缓存失效的场景有哪些?(面试加分)

核心答案:4种常见场景:

  • 用户手动清除浏览器缓存(如设置中清除浏览数据)

  • 用户进行强制刷新(Ctrl + F5)

  • 服务器修改了缓存控制字段(如修改Cache-Control、ETag、Last-Modified)

  • 静态资源文件名发生变化(如hash值改变,触发缓存破坏)

八、面试标准回答模板(必背,直接套用)

当面试官问:"请讲一下浏览器缓存机制?",按以下结构回答(流畅、有条理,加分):

  1. 浏览器缓存主要分为强缓存和协商缓存,两者合称HTTP缓存,是面试重点;还有一种Service Worker缓存,属于可编程缓存,非重点。

  2. 强缓存的核心是"不发请求,直接用缓存",由Cache-Control和Expires控制,其中Cache-Control优先级更高,常用指令有max-age、no-cache、no-store等,未过期时返回200 (from disk/memory cache)。

  3. 协商缓存的核心是"发请求,服务器决定是否用缓存",有两种实现方式:ETag+If-None-Match(基于内容,更精准)和Last-Modified+If-Modified-Since(基于时间,有缺陷),ETag优先级更高,未修改返回304,已修改返回200。

  4. 完整请求流程:先判断强缓存,未过期直接用;过期则进入协商缓存,服务器验证资源状态,未修改用缓存,已修改下载新资源;两者都没有则正常请求。

  5. 生产环境应用:静态资源(带hash)设1年强缓存,通过文件名hash实现缓存破坏;HTML不做强缓存,避免引用旧资源。

🔥 总结一句话(面试收尾,加深印象)

浏览器请求资源时,优先走强缓存,不发请求、直接复用本地资源;强缓存过期后走协商缓存,通过ETag或Last-Modified向服务器验证资源状态,未变化返回304复用缓存,已变化返回200获取新资源,最终实现"高效加载、节省带宽"的目的。

相关推荐
小码哥_常1 小时前
Kotlin函数进阶:解锁可变参数与局部函数的奇妙用法
前端
滕青山1 小时前
正则表达式测试 在线工具核心JS实现
前端·javascript·vue.js
不可能的是1 小时前
前端图片懒加载方案全解析
前端·javascript
不可能的是1 小时前
前端 SSE 流式请求三种实现方案全解析
前端·http
wuhen_n1 小时前
Fragment 与 Portal 的特殊处理
前端·javascript·vue.js
Wect1 小时前
LeetCode 207. 课程表:两种解法(BFS+DFS)详细解析
前端·算法·typescript
珠玑不御1 小时前
从零开始捡起知识点(二)原型
前端
3GPP仿真实验室2 小时前
【MATLAB源码】OTFS-SCMA:链路仿真平台
前端
JarvanMo2 小时前
NativePHP 移动版现已免费:用 Laravel 打造原生 iOS 和 Android 应用
前端