Skip to content

HTTP 缓存

HTTP 缓存是浏览器性能优化里最基础也最常见的一层。它的目标不是“永远不发请求”,而是让浏览器在合适的时候复用已有响应,减少网络开销和等待时间。

为什么需要 HTTP 缓存

如果页面中的脚本、样式、图片、接口响应每次都重新下载,会带来:

  • 更高的网络延迟
  • 更多带宽消耗
  • 更差的首屏和交互体验

HTTP 缓存就是浏览器和服务器之间关于“这份资源还能不能继续用”的一套协商机制。

两类缓存思路

强缓存

在缓存有效期内,浏览器直接使用本地副本,不会发起真正的资源请求。

常见响应头:

  • Cache-Control
  • Expires

协商缓存

浏览器会先问服务器“本地这份还能用吗”,如果能用,服务器返回 304 Not Modified,浏览器继续使用本地缓存副本。

常见响应头:

  • ETag / If-None-Match
  • Last-Modified / If-Modified-Since

Cache-Control

现代缓存控制主要看 Cache-Control

max-age

表示资源在多少秒内可直接复用。

http
Cache-Control: max-age=3600

no-cache

不是“不缓存”,而是“使用前必须先向服务器确认”。

http
Cache-Control: no-cache

no-store

不允许缓存,请求和响应都不应存储。

http
Cache-Control: no-store

public

允许共享缓存使用,例如 CDN。

private

只允许浏览器私有缓存使用,不适合共享缓存。

Expires

老的绝对时间缓存头。

http
Expires: Wed, 26 Jun 2026 12:00:00 GMT

如果同时存在:

  • Cache-Control
  • Expires

通常以 Cache-Control 为准。

协商缓存细节

ETag / If-None-Match

服务器返回资源标识:

http
ETag: "abc123"

浏览器下次请求时带上:

http
If-None-Match: "abc123"

如果资源没变,服务端返回:

http
304 Not Modified

Last-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
  • 排查缓存问题时,分清是强缓存、协商缓存,还是根本没有命中缓存。

基于 MIT 许可发布