浏览器缓存和HTTP 缓存是提升网页加载速度和用户体验的重要手段。它们通过将资源(如 HTML、CSS、JavaScript、图片等)存储在客户端或中间服务器上,减少重复请求和网络传输,从而加快网页的加载速度,减少服务器负载。
一、浏览器缓存与 HTTP 缓存概述
浏览器缓存:指的是浏览器将访问过的资源存储在本地缓存中,当用户再次访问同一资源时,可以直接从缓存中读取,而不是重新向服务器请求。浏览器缓存通过 HTTP 缓存机制实现。
HTTP 缓存:通过 HTTP 协议中的缓存控制头字段(如
Cache-Control
、Expires
、ETag
等)来控制资源的缓存策略。HTTP 缓存机制决定了资源是否从缓存中读取或需要向服务器请求。
二、HTTP 缓存控制的常见方法
HTTP 缓存机制主要通过响应头字段来控制,以下是几种常见的缓存控制方式:
1. Cache-Control
响应头
Cache-Control
是最常用的 HTTP 头之一,允许服务器控制资源的缓存行为。它提供了多种指令来设置缓存策略。
常见指令:
Cache-Control: no-cache
:不使用本地缓存,每次都必须发送请求到服务器进行验证。如果服务器验证资源未更改,可以返回 304(Not Modified)状态码,客户端可以使用缓存的副本,但必须经过服务器验证。Cache-Control: no-store
:完全不缓存资源,浏览器或代理服务器不会保存资源的任何副本,每次都必须向服务器请求资源。Cache-Control: public
:资源可以被任何缓存存储,包括代理服务器缓存和浏览器缓存。Cache-Control: private
:资源只能被浏览器缓存,不能被代理服务器缓存。Cache-Control: max-age=[seconds]
:资源可以在本地缓存多长时间(以秒为单位)。在这段时间内,浏览器直接使用缓存,避免向服务器发送请求。Cache-Control: must-revalidate
:缓存的资源必须先验证是否过期,如果过期,则需要重新请求服务器。
示例:
Cache-Control: public, max-age=3600 // 资源可以缓存1小时
Cache-Control: no-store // 禁止缓存
2. Expires
响应头
Expires
是 HTTP 1.0 中的缓存机制,用于指定资源的过期时间(绝对时间)。在指定的时间之前,浏览器会直接使用缓存,而不会向服务器请求。Expires
已经被 Cache-Control
的 max-age
替代,但仍然被部分浏览器支持。
示例:
Expires: Wed, 21 Oct 2024 07:28:00 GMT
优缺点:
Expires
使用的是绝对时间,如果客户端和服务器的时间不同步,会导致缓存控制失效。因此,现代应用更多使用Cache-Control: max-age
。
3. ETag
(实体标签)与 Last-Modified
ETag
和 Last-Modified
都是用来判断缓存资源是否发生变化的两种方式。它们用于协商缓存(conditional caching),即在缓存资源过期时,通过向服务器请求来判断资源是否更新。
ETag
:资源的唯一标识符(哈希值)。当浏览器再次请求资源时,浏览器会将缓存的ETag
发送给服务器,服务器通过比较ETag
值来判断资源是否更新。如果未更新,则返回304 Not Modified
状态码,浏览器可以使用缓存资源。示例:
httpETag: "5d8c72a5f8d2a"
Last-Modified
:标识资源的最后修改时间。浏览器在后续请求时,会通过If-Modified-Since
头发送上次获取到的Last-Modified
时间,服务器根据该时间来判断资源是否有更新。示例:
httpLast-Modified: Wed, 21 Oct 2023 07:28:00 GMT
客户端请求:
httpIf-Modified-Since: Wed, 21 Oct 2023 07:28:00 GMT
服务器响应:
httpHTTP/1.1 304 Not Modified
三、常见缓存策略及其优缺点
1. 强缓存(强制缓存)
强缓存(也称为强制缓存)是指在缓存有效期内,浏览器直接从本地缓存中加载资源,不与服务器通信。常用的控制头有 Cache-Control: max-age
和 Expires
。
优点:
- 资源加载速度快,完全避免了网络请求,节省带宽。
- 提升用户体验,特别是在慢速网络或离线场景中。
缺点:
- 如果资源在缓存有效期内发生变化,用户无法及时获取最新资源,导致数据过时。
示例:
Cache-Control: max-age=86400 // 缓存1天
Expires: Wed, 21 Oct 2024 07:28:00 GMT
2. 协商缓存
协商缓存是指当缓存过期时,浏览器向服务器发送请求,询问资源是否有更新。如果资源没有更新,服务器返回 304 Not Modified
,浏览器可以继续使用缓存;如果资源更新,则返回新的资源。
优点:
- 在资源更新时,用户可以及时获取到最新的内容。
- 减少了不必要的资源传输,优化了带宽。
缺点:
- 仍然会发起网络请求,虽然节省了传输内容的时间,但仍有网络延迟。
示例:
ETag: "5d8c72a5f8d2a"
Last-Modified: Wed, 21 Oct 2023 07:28:00 GMT
四、浏览器缓存的常见用法
1. 针对静态资源的缓存策略
静态资源(如 JS、CSS、图片等)通常使用强缓存策略,配合文件版本号控制。当资源内容发生变化时,修改文件的版本号,保证用户获取到最新的资源。
示例:
Cache-Control: public, max-age=31536000 // 静态资源缓存1年
通过在文件名中加上版本号的方式来控制更新,如:
<script src="app.v1.0.0.js"></script>
当资源有更新时,版本号变为 v1.0.1
:
<script src="app.v1.0.1.js"></script>
这样可以保证缓存命中的前提下也能获取到最新的资源。
2. 针对 API 请求的缓存策略
对于动态内容或频繁更新的 API 请求,一般使用协商缓存或禁止缓存的策略。这样可以确保用户始终获取到最新的数据。
示例:
Cache-Control: no-cache, must-revalidate // 请求时必须先验证资源是否最新
3. 对于敏感数据禁止缓存
对于敏感数据(如登录页面、用户隐私数据),应当禁止缓存,防止缓存中的数据泄露。
示例:
Cache-Control: no-store // 禁止缓存任何内容
五、浏览器缓存的优缺点总结
优点
- 提升加载速度:缓存使浏览器可以直接从本地读取资源,而不必重新向服务器请求,减少网络传输时间,加快页面加载速度。
- 减少服务器负载:缓存减少了服务器的请求次数,降低了服务器的压力。
- 节省带宽:对于重复资源,缓存减少了带宽消耗,尤其在流量受限的网络环境中效果显著。
缺点
- 数据过时问题:使用强缓存时,资源如果在缓存有效期内发生更新,用户可能无法及时获取到最新的内容。
- 缓存失效控制复杂:对于频繁更新的资源,需要精心设计缓存策略来确保用户获取到最新资源,避免过时内容。
- 缓存占用空间:浏览器缓存会占用用户设备的存储空间,过多的缓存可能导致用户设备性能问题。
六、总结
浏览器缓存和 HTTP 缓存是提升网页性能的重要手段,合理的缓存策略能够显著改善页面的加载速度、节省服务器资源,并为用户提供更好的使用体验。常用的缓存策略包括:
- 强缓存:通过
Cache-Control: max-age
或Expires