前端知识速记:浏览器缓存机制 - 强缓存与协商缓存
前端知识速记:浏览器缓存机制 - 强缓存与协商缓存
浏览器缓存是提升Web应用性能的关键技术之一。通过将静态资源(如CSS、JavaScript、图片等)存储在浏览器本地,可以避免重复从服务器下载,显著减少页面加载时间,改善用户体验。
一、浏览器缓存机制概述
浏览器缓存主要分为两种:强缓存(也称为本地缓存)和 协商缓存(也称为弱缓存)。
- 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命中,则直接从缓存中读取资源,无需向服务器发送任何请求。
- 协商缓存: 当强缓存未命中时,浏览器会向服务器发送请求,询问服务器资源是否发生变化。如果服务器告知资源未改变,则浏览器从缓存中读取资源;如果服务器告知资源已改变,则浏览器会下载新资源并更新缓存。
二、强缓存(Local Cache)
强缓存通过 HTTP 响应头中的 Cache-Control
或 Expires
字段来控制。
1. Cache-Control
Cache-Control
是一个更加现代且功能强大的缓存控制字段。它支持多种指令,常见的包括:
max-age=<seconds>
: 指定资源被缓存的最大时间,单位为秒。例如,Cache-Control: max-age=3600
表示资源可以被缓存 1 小时。s-maxage=<seconds>
: 类似于max-age
,但只对共享缓存(例如 CDN)有效。private
: 表示资源只能被用户私有的浏览器缓存,不允许被共享缓存。public
: 表示资源可以被任何缓存(包括私有缓存和共享缓存)缓存。no-cache
: 强制浏览器进行协商缓存,即每次使用缓存资源前都需要向服务器确认资源是否过期。 虽然名字叫no-cache
,但实际上仍然允许浏览器缓存资源。no-store
: 禁止浏览器和所有中间缓存存储任何版本的响应。 资源不进行缓存。
示例:
HTTP/1.1 200 OK
Content-Type: image/jpeg
Cache-Control: max-age=86400, public
上述响应头表示该图片资源可以被缓存 24 小时,并且可以被任何缓存(包括 CDN)缓存。
2. Expires
Expires
指定资源失效的绝对时间,是一个日期时间字符串。 Expires
基于客户端时间,因此如果客户端时间与服务器时间不同步,可能会导致缓存失效。
示例:
HTTP/1.1 200 OK
Content-Type: image/jpeg
Expires: Thu, 01 Dec 2023 16:00:00 GMT
上述响应头表示该图片资源在 2023 年 12 月 1 日 16:00:00 GMT 之后失效。
注意: 如果同时设置了 Cache-Control
和 Expires
,Cache-Control
的优先级更高。
三、协商缓存(Conditional Cache)
当强缓存未命中时,浏览器会向服务器发送请求,通过 If-Modified-Since
和 If-None-Match
请求头询问服务器资源是否发生变化。服务器根据请求头中的信息判断资源是否过期,并返回相应的状态码和响应头。
1. Last-Modified
和 If-Modified-Since
Last-Modified
: 服务器在响应头中返回资源的最后修改时间。If-Modified-Since
: 浏览器在请求头中携带上次服务器返回的Last-Modified
值,询问服务器资源自该时间以来是否发生变化。
流程:
- 浏览器第一次请求资源时,服务器返回
Last-Modified
响应头。 - 浏览器再次请求该资源时,会在请求头中携带
If-Modified-Since
,值为上次响应的Last-Modified
值。 - 服务器比较
If-Modified-Since
与资源的最后修改时间:- 如果资源未修改,则返回
304 Not Modified
状态码,不返回资源内容。 - 如果资源已修改,则返回
200 OK
状态码,并返回新的资源内容和新的Last-Modified
值。
- 如果资源未修改,则返回
示例:
第一次请求:
HTTP/1.1 200 OK
Content-Type: image/jpeg
Last-Modified: Tue, 21 Nov 2023 10:00:00 GMT
第二次请求:
GET /image.jpg HTTP/1.1
If-Modified-Since: Tue, 21 Nov 2023 10:00:00 GMT
服务器响应(资源未修改):
HTTP/1.1 304 Not Modified
2. ETag
和 If-None-Match
ETag
: 服务器为资源生成的唯一标识符,可以是资源的哈希值或其他算法生成的值。If-None-Match
: 浏览器在请求头中携带上次服务器返回的ETag
值,询问服务器资源是否发生变化。
流程:
- 浏览器第一次请求资源时,服务器返回
ETag
响应头。 - 浏览器再次请求该资源时,会在请求头中携带
If-None-Match
,值为上次响应的ETag
值。 - 服务器比较
If-None-Match
与资源的ETag
值:- 如果
ETag
值相同,则返回304 Not Modified
状态码,不返回资源内容。 - 如果
ETag
值不同,则返回200 OK
状态码,并返回新的资源内容和新的ETag
值。
- 如果
示例:
第一次请求:
HTTP/1.1 200 OK
Content-Type: image/jpeg
ETag: "637F7F7F7F7F7F7F"
第二次请求:
GET /image.jpg HTTP/1.1
If-None-Match: "637F7F7F7F7F7F7F"
服务器响应(资源未修改):
HTTP/1.1 304 Not Modified
注意: ETag
比 Last-Modified
更精确,因为 ETag
可以检测到即使资源内容没有变化,但最后修改时间发生了变化的情况。 如果同时设置了 Last-Modified
和 ETag
,服务器会优先验证 ETag
。
四、实际应用场景
- 图片、CSS、JavaScript 等静态资源: 可以使用强缓存,设置较长的
max-age
值。 - HTML 文件: 通常使用协商缓存,确保用户总是获取到最新的页面内容。
- API 接口: 可以根据 API 的特性选择合适的缓存策略。
五、强缓存与协商缓存对比
特性 | 强缓存 (Local Cache) | 协商缓存 (Conditional Cache) |
---|---|---|
控制字段 | Cache-Control , Expires | Last-Modified /If-Modified-Since , ETag /If-None-Match |
请求服务器 | 无需请求服务器 | 需要请求服务器进行验证 |
状态码 | 200 OK (from cache) / 200 OK (来自内存/硬盘缓存) | 304 Not Modified (使用缓存) / 200 OK (返回新资源) |
资源新鲜度判断 | 基于过期时间和客户端时间 | 基于服务器资源是否发生变化 |
适用场景 | 静态资源,不经常变化的资源 | 动态资源,需要验证新鲜度的资源 |
优先级 | 高 | 低,在强缓存失效后才会生效 |