面试导航 是一个专注于前、后端技术学习和面试准备的 免费 学习平台,提供系统化的技术栈学习,深入讲解每个知识点的核心原理,帮助开发者构建全面的技术体系。平台还收录了大量真实的校招与社招面经,帮助你快速掌握面试技巧,提升求职竞争力。如果你想加入我们的交流群,欢迎通过微信联系:
yunmz777
。
强缓存和协商缓存基本概念
浏览器缓存是浏览器在本地存储用户最近请求的资源,以便在后续访问相同页面时能更快加载,提高性能并减少服务器负担。根据缓存策略,浏览器缓存可分为 强缓存 和 协商缓存:
-
强缓存:浏览器在请求资源时,会根据响应头中的缓存策略判断是否直接使用本地缓存副本,而无需向服务器发送请求。如果资源符合强缓存规则,浏览器将直接从本地加载,避免网络请求,从而加快页面加载速度并降低服务器压力。
-
协商缓存:当资源可能已过期或发生变化时,浏览器会向服务器发送请求,并附带特定的条件信息(如
ETag
或Last-Modified
)。服务器根据这些信息判断资源是否更新,并返回相应的状态码。如果资源未修改,服务器返回304 Not Modified
,浏览器继续使用本地缓存;否则,服务器返回新的资源,浏览器更新缓存。
这种缓存机制能在保证资源最新性的同时,提高加载效率,优化用户体验。
浏览器缓存的主要优点包括以下几个方面:
-
提高页面加载速度:缓存可以让浏览器直接从本地加载资源,而无需重新请求服务器,减少网络延迟,使网页打开速度更快,提升用户体验。
-
降低服务器压力:通过缓存静态资源(如 CSS、JS、图片等),可以减少服务器的重复请求,降低带宽消耗和服务器负载,提升网站的可扩展性。
-
节省带宽:浏览器缓存减少了重复下载相同资源的需求,尤其在用户访问相同网站的多个页面时,可以显著降低流量消耗,提高访问效率。
-
支持离线访问:结合 Service Worker 缓存,浏览器可以在没有网络的情况下加载缓存的内容,使 PWA(渐进式 Web 应用)等离线体验更加流畅。
-
提升用户体验:页面加载速度更快、减少网络请求等待时间,以及支持离线访问,都能让用户获得更顺畅的浏览体验,提高网站的用户留存率。
-
提高资源利用率:对于较大的静态资源,如视频、字体、图片等,缓存可以避免重复下载,提高网络资源的利用效率,减少服务器和用户的资源开销。
通过合理的缓存策略,浏览器缓存能在 速度、流量、服务器负载和用户体验 之间取得平衡,使 Web 应用更加高效。
浏览器缓存,那它到底是缓存在哪里?
浏览器缓存主要存储在 内存 和 磁盘,不同类型的缓存决定了数据的存储位置和存活时间。接下来我们将详细介绍各种缓存机制及其应用场景。
内存缓存(Memory Cache)
内存缓存将资源存储在 RAM 中,访问速度最快,适用于当前页面加载过程中频繁使用的资源,如 CSS、JS 和图片。它的生命周期较短,一旦页面关闭或刷新,部分缓存可能被释放。
特点:
- 读取速度最快
- 时效性短,随浏览器进程结束而释放
- 容量有限,一般不会存储太大的资源
- 常用于存储解码后的图片、CSS 样式表等
磁盘缓存(Disk Cache)
磁盘缓存将资源存储在本地硬盘上,适用于体积较大、生命周期较长的资源。相比内存缓存,它的访问速度稍慢,但能在浏览器关闭后仍然生效,减少后续请求。
特点:
- 存储容量大
- 持久化存储,重启浏览器后仍可使用
- 适合存储较大文件
- 通常会根据文件类型、资源大小等因素智能分配存储位置
Service Worker 缓存(Cache Storage)
Service Worker 提供了一种可编程的缓存方式,允许开发者手动管理缓存的资源,存储在 Cache Storage
中。
主要特性:
- 支持离线访问能力
- 可编程的缓存策略
- 独立于主线程的后台运行
- 网络代理能力
- 常用于实现 PWA 应用
示例代码:
javascript
// Service Worker 注册示例
if ("serviceWorker" in navigator) {
navigator.serviceWorker
.register("/sw.js")
.then((registration) => {
console.log("ServiceWorker registration successful");
})
.catch((err) => {
console.log("ServiceWorker registration failed: ", err);
});
}
HTTP 缓存
HTTP 缓存分为强缓存和协商缓存两种机制:
强缓存:
-
Cache-Control: 现代浏览器使用的主要机制
- max-age:指定资源有效期
- no-cache:强制验证缓存
- no-store:禁止缓存
- private/public:指定缓存作用域
-
Expires:早期的过期时间控制(已逐渐被 Cache-Control 取代)
协商缓存:
-
ETag/If-None-Match:基于资源内容的验证
-
Last-Modified/If-Modified-Since:基于时间的验证
DNS 缓存
DNS 缓存分为多个层级:
- 浏览器 DNS 缓存
- 操作系统 DNS 缓存
- 路由器 DNS 缓存
- ISP DNS 缓存
可以通过以下 DNS 预解析来优化:
html
<link rel="dns-prefetch" href="//example.com" />
预解析/预加载缓存(Prefetch / Preload)
现代浏览器提供了多种资源预加载机制:
- preload:当前页面必需资源
html
<link rel="preload" href="style.css" as="style" />
- prefetch:未来页面可能需要的资源
html
<link rel="prefetch" href="next-page.js" />
- preconnect:提前建立连接
html
<link rel="preconnect" href="https://example.com" />
浏览器会根据资源类型、使用频率和缓存策略来决定数据的存储位置,以平衡访问速度和存储效率。合理利用各种缓存机制,可以显著提升网站性能和用户体验。
强缓存和协商缓存工作流程
首先我们先栏看强缓存和协商缓存的工作流程图,如下所示:
当浏览器请求资源(如 HTML、CSS、JS、图片等)时,会先检查缓存,决定是直接使用缓存还是向服务器请求新资源。整个缓存机制主要分为 强缓存 和 协商缓存 两种策略。
强缓存 (Freshness)
强缓存是指在本地缓存资源未过期的情况下,浏览器直接使用缓存,不发送请求给服务器,提高访问速度。
浏览器根据 Cache-Control
或 Expires
头信息判断缓存是否仍然有效:
-
Cache-Control: max-age=3600
:表示资源在 3600 秒(即 1 小时)内有效,不需要重新请求服务器。 -
Expires: Wed, 21 Oct 2025 07:28:00 GMT
:资源的绝对过期时间,若未超过此时间,直接使用缓存。
主要的处理流程如下:
- 浏览器请求资源后,若
Cache-Control
或Expires
指示缓存仍有效,则直接从缓存读取资源,无需网络请求。 - 若缓存过期,则进入 协商缓存 阶段。
协商缓存 (Revalidation)
如果强缓存失效,浏览器不会立即下载新资源,而是向服务器发起 条件请求,询问资源是否发生了变化,服务器通过特定头信息返回是否需要更新。
ETag 校验
ETag
是服务器生成的资源唯一标识符,若资源修改,ETag
也会更新。
请求流程:
-
浏览器请求资源时,服务器返回资源及
ETag
值,例如:vbnetETag: "abc123"
-
资源缓存后,浏览器下次请求时,在请求头中添加:
sqlIf-None-Match: "abc123"
-
服务器接收请求后:
-
若
ETag
未变 (资源未修改),返回304 Not Modified
,浏览器直接使用缓存。 -
若
ETag
变化 (资源已修改),返回200 OK
,并提供新资源。
-
Last-Modified 校验
若服务器未使用 ETag
,浏览器会改用 Last-Modified
进行时间校验。
请求流程:
-
服务器首次返回资源时,包含
Last-Modified
头,例如:yamlLast-Modified: Tue, 12 Mar 2024 10:00:00 GMT
-
浏览器下次请求时,在请求头中携带:
yamlIf-Modified-Since: Tue, 12 Mar 2024 10:00:00 GMT
-
服务器接收请求后:
-
若资源未修改 (时间未变),返回
304 Not Modified
,浏览器使用缓存。 -
若资源已修改 (时间更新),返回
200 OK
,并提供新资源。
-
服务器响应
服务器根据 ETag
或 Last-Modified
进行校验后,返回相应的状态码:
状态码 | 含义 |
---|---|
200 OK | 资源有更新,返回新内容,并更新 ETag 或 Last-Modified 。 |
304 Not Modified | 资源未更改,浏览器使用缓存,不返回内容。 |
当 304
返回时,浏览器不会重新下载资源,只会复用本地缓存文件,从而节省带宽。
关键缓存字段
其中,在上面的流程中,又有几个令人难懂的字段,如下:
头部字段 | 作用 |
---|---|
ETag | 资源唯一标识,变化表示资源已修改。 |
Expires | 绝对过期时间,浏览器用于强缓存判断。 |
Cache-Control | 详细缓存策略,如 max-age 、no-cache 、must-revalidate 。 |
Last-Modified | 资源最后修改时间,用于协商缓存判断。 |
If-None-Match | 浏览器携带 ETag 进行验证,匹配则返回 304 。 |
If-Modified-Since | 浏览器携带 Last-Modified 进行验证,时间一致则返回 304 。 |
小结
-
强缓存 (
Cache-Control
/Expires
):如果资源未过期,直接从缓存加载,无需请求服务器。 -
协商缓存 (
ETag
/Last-Modified
):如果缓存过期,浏览器询问服务器资源是否更新:-
ETag
优先 (更精准),匹配则304
。 -
无
ETag
时,用Last-Modified
,时间一致则304
。
-
-
最终处理
-
304 Not Modified
:浏览器使用缓存,无需重新下载资源。 -
200 OK
:服务器返回新资源,并更新缓存策略。
-
这样既减少了服务器请求次数,也保证了资源的最新状态,提升了性能和用户体验。
图解强缓存和协商缓存
在上面的内容中讲了这么多的理论, 你是否还是不太理解什么是 强缓存
和 协商缓存
啊,那么接下来我们就用几张图片来弄清楚这两者的区别。
强缓存
强缓存就是文件直接从本地缓存中获取,不需要发送请求。
首次请求
当浏览器发送初次请求时,浏览器会向服务器发起请求,服务器接收到浏览器的请求后,返回资源并返回一个 Cache-Control
字段给客户端,在该字段中设置一些缓存相关的信息,例如最大过期时间。
再次请求
在前面的基础上,浏览器再次发送请求,浏览器一节接收到 Cache-Control
的值,那么这个时候浏览器它会首先检查它的 Cache-Control
是否过期,如果没有过期则直接从本地缓存中拉取资源,返回割到客户端,则无需再经过服务器。
缓存失效
强缓存有过期时间,那么就意味着总有一天缓存会失效,如果客户端的 Cache-Control
失效了,那么它就会像首次请求中一样,重新向服务器发起请求,之后服务器会再次返回资源和 Cache-Control
的值。
协商缓存
协商缓存也叫做对比缓存,服务端判断客户端的资源是否和服务端的一样,如果一样则返回 304
,反之返回 200
和最新的资源。
初次请求
如果客户端是第一次向服务器发出请求,则服务器返回资源和对应的资源标识给浏览器,该资源标识就是对当前所返回资源的唯一标识,可以是 ETag
或者是 Last-Modified
。
之后如果浏览器再次发送请求是,浏览器就会带上这个资源表,此时服务端就会通过这个资源标识,可以判断出浏览器的资源跟服务器此时的资源是否一致,如果一致则返回 304 Not Modified
,如果不一致,则返回 200
,并返回资源以及新的资源标识。
不同刷新操作方式,对强制缓存和协商缓存的影响
普通刷新(F5 或点击刷新按钮)
- 强制缓存(Cache-Control / Expires):如果缓存未过期,浏览器直接使用缓存;如果缓存过期,则进入协商缓存流程。
- 协商缓存(ETag / Last-Modified) :如果强缓存过期,浏览器向服务器发送
If-Modified-Since
或If-None-Match
头,服务器检查资源是否更新:- 未修改 :返回
304 Not Modified
,浏览器使用缓存数据。 - 已修改 :返回
200 OK
,并提供新资源。
- 未修改 :返回
- 服务器负担:如果缓存命中,则负担较小;如果缓存过期,则需要服务器参与协商缓存。
强制刷新(Ctrl + F5 或 Shift + 刷新按钮)
- 强制缓存 :浏览器忽略所有缓存策略,无论
Cache-Control
或Expires
是否有效,都会直接向服务器请求最新资源。 - 协商缓存 :浏览器不会发送
If-Modified-Since
或If-None-Match
,直接获取完整的新资源。 - 服务器负担:最大,所有资源都会重新下载。
地址栏回车
- 强制缓存:如果缓存未过期,直接使用缓存;如果缓存过期,则进入协商缓存流程。
- 协商缓存 :如果强缓存失效,浏览器会向服务器发送
If-Modified-Since
或If-None-Match
进行协商缓存验证。 - 服务器负担:和普通刷新类似,适中。
前进 / 后退
- 强制缓存 :通常使用
Memory Cache
(内存缓存),如果页面仍在内存中,不会向服务器请求,直接使用缓存数据。 - 协商缓存 :通常不会触发请求,即使缓存过期,浏览器仍可能直接使用
Memory Cache
或Disk Cache
。 - 服务器负担:最小,几乎不产生额外的服务器请求。
清空缓存后刷新
- 强制缓存:缓存已清空,浏览器没有可用的缓存数据,必须重新向服务器请求所有资源。
- 协商缓存:由于无缓存数据可用于协商,所有请求都需要服务器返回完整资源。
- 服务器负担:最大,等同于用户首次访问网站。
小结
刷新方式 | 强制缓存 | 协商缓存 | 服务器负担 |
---|---|---|---|
F5 | 可能使用 | 失效时生效,返回 304 或 200 |
适中 |
Ctrl + F5 | 跳过缓存,直接请求服务器 | 跳过协商缓存,请求最新资源 | 高 |
地址栏回车 | 可能使用 | 失效时生效,返回 304 或 200 |
适中 |
前进 / 后退 | 直接使用 Memory Cache |
很少触发 | 低 |
清空缓存后刷新 | 不使用,直接请求 | 不使用,直接请求 | 高 |
不同刷新方式的应用场景:
-
普通刷新(F5) 适用于检查页面是否有更新,同时减少不必要的服务器请求。
-
强制刷新(Ctrl + F5) 适用于确保获取最新内容,如前端开发调试或页面异常。
-
地址栏回车 适用于正常访问网站,与 F5 类似。
-
前进 / 后退 适用于快速浏览历史页面,提高页面切换速度。
-
清空缓存后刷新 适用于解决缓存导致的问题,如 CSS/JS 资源未更新。
合理利用不同的刷新方式可以提高页面加载速度,同时减少服务器负担。
总结
强缓存 (本地缓存)是指在资源的缓存有效期内,浏览器无需向服务器发送请求,直接使用本地缓存的数据,提高页面加载速度,减少网络请求。它主要依赖 Cache-Control: max-age
或 Expires
头信息来控制资源的有效期,当缓存未过期时,浏览器不会发起请求。
协商缓存 (条件请求)是在强缓存失效后,浏览器向服务器发送请求,并携带 ETag
或 Last-Modified
进行资源校验。服务器通过比对 ETag
或 Last-Modified
判断资源是否更新,若资源未变更,则返回 304 Not Modified
,浏览器继续使用缓存,否则返回 200 OK
并提供新资源。
两者结合使用可以优化网页加载性能,减少服务器压力,同时确保数据的时效性。