HTTP缓存是提升Web性能的关键技术,通过将资源保存在客户端或代理服务器上,减少重复请求。
核心机制分为强缓存(直接使用本地副本)和协商缓存(需服务器验证),通过Expires、Cache-Control、ETag等头部字段控制。
最佳实践包括:
- 为静态资源添加哈希指纹实现长缓存;
- HTML文件设置no-cache确保及时更新;
- 敏感数据使用no-store避免缓存;
合理配置缓存策略能显著提升加载速度、节省带宽并降低服务器压力。
HTTP缓存详解
HTTP缓存是Web性能优化的核心技术之一,能显著减少网络延迟、节省带宽并降低服务器负载。下面我将从核心概念、工作机制、关键头字段、缓存策略等方面进行详解。
一、核心概念
HTTP缓存的核心思想是:将请求过的资源(如HTML、CSS、JS、图片)保存在客户端(浏览器)或中间的代理服务器上,当再次需要相同资源时,可以直接从本地或代理获取,而无需重新从源服务器下载。
主要好处:
-
加快页面加载速度,提升用户体验。
-
减少网络流量,为用户节省带宽。
-
降低服务器压力,提高服务能力。
二、缓存位置
-
私有缓存:通常是浏览器自身的缓存,只为单个用户服务。
-
共享缓存:位于客户端和服务器之间,为多个用户服务。
-
代理缓存:如公司网络中的缓存代理。
-
CDN缓存:内容分发网络中的边缘节点缓存。
-
三、关键HTTP头部字段
缓存行为主要由HTTP请求和响应的头部字段控制。
1. 强缓存验证字段(无需向服务器发起请求)
浏览器直接判断是否使用本地缓存,不发送请求到服务器。
-
Expires(HTTP/1.0)-
值是一个绝对的过期时间(GMT格式)。
-
缺点:依赖客户端时间,如果时间不同步会导致缓存失效不准。
-
-
Cache-Control(HTTP/1.1)-
优先级高于
Expires。 -
常用指令:
-
max-age=:资源的最大存活时间(秒),从请求开始计算。例如max-age=31536000表示一年。 -
public:响应可以被任何对象(客户端、代理服务器)缓存。 -
private:响应只能被单个用户的浏览器缓存,不允许代理服务器缓存。 -
no-cache:不是不缓存,而是使用缓存前必须向服务器验证(即进入协商缓存流程)。 -
no-store:真正的不缓存,不存储任何客户端或代理的缓存。用于敏感数据。 -
s-maxage:覆盖max-age,但仅适用于共享缓存(如CDN)。
-
-
2. 协商缓存验证字段(需要与服务器通信验证)
当强缓存失效或设置了no-cache时,浏览器会携带验证字段向服务器发起请求。服务器根据这些字段判断资源是否变更。
-
Last-Modified/If-Modified-Since-
服务器在响应头中返回
Last-Modified,表示资源的最后修改时间。 -
浏览器再次请求时,在请求头中带上
If-Modified-Since,值为之前收到的Last-Modified。 -
服务器比较时间,如果未修改,则返回
304 Not Modified(空Body);如果已修改,则返回200 OK和新资源。 -
缺点 :精度到秒,一秒内的修改无法感知;文件可能只是被
touch修改了时间但内容未变。
-
-
ETag/If-None-Match-
优先级高于
Last-Modified。 -
服务器在响应头中返回
ETag,通常是文件内容的哈希值或版本号(如"33a64df551425fcc55e4d42a148795d9f25f89d4")。 -
浏览器再次请求时,在请求头中带上
If-None-Match,值为之前收到的ETag。 -
服务器比较
ETag,如果一致则返回304,不一致则返回200和新资源。 -
优点 :能精确感知内容变化。缺点 :计算
ETag有服务器性能开销。
-
四、缓存工作流程(核心)
下图清晰地展示了浏览器处理HTTP缓存的完整决策过程:

简单来说,浏览器会优先检查强缓存,如果命中且未过期,则直接使用本地资源(极快)。否则,就会发起请求与服务器进行协商缓存验证,根据资源是否变化来决定是使用本地副本还是下载新资源。
五、常见的缓存策略模式
-
永久不变的文件 (如打包后的带哈希指纹的
app.a1b2c3.js)Cache-Control: public, max-age=31536000, immutable- 设置长缓存(一年),
immutable告诉浏览器即使用户刷新页面,也无需验证直接使用缓存。
- 设置长缓存(一年),
-
经常变动的文件 (如
index.html)Cache-Control: no-cache-
或
max-age=0, must-revalidate。 -
每次都向服务器验证,确保获取最新的页面骨架。
-
-
用户隐私或敏感数据
Cache-Control: private, no-cache- 或
no-store(更严格)。
- 或
-
静态资源(无指纹) (如
common.css)Cache-Control: public, max-age=86400 ETag: "xyz123"- 设置一个较短的缓存时间(一天),配合
ETag进行验证。
- 设置一个较短的缓存时间(一天),配合
六、实践技巧与注意事项
-
哈希指纹 :为静态资源文件名添加内容哈希(如
style.a1b2c3.css),这样一旦文件内容改变,文件名就变,相当于强制下载新文件。这是实现"长缓存"的最佳实践。 -
CDN缓存 :注意
Cache-Control头也会影响CDN行为。通常CDN会尊重源站的缓存头。 -
用户行为影响:
-
正常打开:遵循上述缓存机制。
-
回车刷新/跳转:浏览器会进行协商缓存验证。
-
强制刷新(Ctrl+F5) :浏览器会忽略所有缓存,请求头带上
Cache-Control: no-cache和Pragma: no-cache,直接从服务器拉取。 -
禁用缓存(开发者工具):所有请求都会绕过缓存。
-
-
Vary头 :用于告知缓存服务器,该资源的内容会根据某些请求头(如User-Agent,Accept-Encoding)的不同而改变。缓存服务器在决定是否使用缓存副本时,必须将这些请求头的值也作为判断依据。
总结
最佳实践组合:
-
HTML文件 :使用
no-cache或较短的max-age,确保能及时更新。 -
带哈希的静态资源(CSS, JS, 图片) :使用
Cache-Control: max-age=31536000, immutable进行长缓存。 -
API接口数据 :通常使用
Cache-Control: no-store或private, max-age=0,避免敏感数据被缓存。对于公开数据,可适当使用max-age或ETag。
理解并合理配置HTTP缓存,是构建高性能Web应用不可或缺的一环。