主题
HTTP 缓存
HTTP 缓存是浏览器性能优化里最基础也最常见的一层。它的目标不是“永远不发请求”,而是让浏览器在合适的时候复用已有响应,减少网络开销和等待时间。
为什么需要 HTTP 缓存
如果页面中的脚本、样式、图片、接口响应每次都重新下载,会带来:
- 更高的网络延迟
- 更多带宽消耗
- 更差的首屏和交互体验
HTTP 缓存就是浏览器和服务器之间关于“这份资源还能不能继续用”的一套协商机制。
两类缓存思路
强缓存
在缓存有效期内,浏览器直接使用本地副本,不会发起真正的资源请求。
常见响应头:
Cache-ControlExpires
协商缓存
浏览器会先问服务器“本地这份还能用吗”,如果能用,服务器返回 304 Not Modified,浏览器继续使用本地缓存副本。
常见响应头:
ETag/If-None-MatchLast-Modified/If-Modified-Since
Cache-Control
现代缓存控制主要看 Cache-Control。
max-age
表示资源在多少秒内可直接复用。
http
Cache-Control: max-age=3600no-cache
不是“不缓存”,而是“使用前必须先向服务器确认”。
http
Cache-Control: no-cacheno-store
不允许缓存,请求和响应都不应存储。
http
Cache-Control: no-storepublic
允许共享缓存使用,例如 CDN。
private
只允许浏览器私有缓存使用,不适合共享缓存。
Expires
老的绝对时间缓存头。
http
Expires: Wed, 26 Jun 2026 12:00:00 GMT如果同时存在:
Cache-ControlExpires
通常以 Cache-Control 为准。
协商缓存细节
ETag / If-None-Match
服务器返回资源标识:
http
ETag: "abc123"浏览器下次请求时带上:
http
If-None-Match: "abc123"如果资源没变,服务端返回:
http
304 Not ModifiedLast-Modified / If-Modified-Since
服务器返回最后修改时间:
http
Last-Modified: Wed, 26 Jun 2026 10:00:00 GMT浏览器下次请求时带上:
http
If-Modified-Since: Wed, 26 Jun 2026 10:00:00 GMT一个典型流程
第一次请求
http
GET /app.js服务端响应:
http
200 OK
Cache-Control: max-age=31536000
ETag: "app-hash"后续请求
如果强缓存还没过期,浏览器直接用本地副本。
如果强缓存过期,浏览器可能带上:
http
If-None-Match: "app-hash"服务端若确认没变,返回:
http
304 Not Modified静态资源和接口缓存的区别
静态资源
通常适合:
- 文件名带 hash
- 长时间强缓存
http
Cache-Control: public, max-age=31536000, immutable接口响应
通常更谨慎,很多接口数据变化频繁,更常见的是:
http
Cache-Control: no-cache或者直接:
http
Cache-Control: no-store常见误区
“no-cache 就是不缓存”
不对。no-cache 的意思是缓存前必须重新验证。
“304 就是没有走缓存”
不对。304 正说明协商缓存生效了,浏览器继续使用本地副本。
“所有资源都该长缓存”
不对。动态接口、用户敏感数据、个性化内容通常不适合长时间强缓存。
开发建议
- 带 hash 的静态资源优先长缓存。
- 接口数据按业务变化频率设置缓存策略,不要一刀切。
- 需要绝对不落盘的敏感响应使用
no-store。 - 排查缓存问题时,分清是强缓存、协商缓存,还是根本没有命中缓存。
