60 秒回答模板

HTTP 缓存先看强缓存,Cache-Control 或 Expires 仍有效时浏览器不发请求,直接用本地缓存。强缓存过期后进入协商缓存,浏览器带 If-None-Match 或 If-Modified-Since 问服务端资源是否变化。服务端判断未变化就返回 304 Not Modified,语义是资源未修改,通常不携带新的响应体,浏览器拿本地缓存的 body 来渲染,并根据响应头更新缓存元信息。ETag/If-None-Match 通常优先级和精度高于 Last-Modified/If-Modified-Since。304 不是错误,也不是重新下载资源。

考点 核心机制与工程取舍
难度 中高频面试题
回答目标 按定义、机制、场景讲清楚

深入解析

01

先分强缓存和协商缓存

强缓存命中时请求不会到服务端;协商缓存会发请求,但请求目的是验证本地副本是否还能用。304 只会出现在协商缓存链路里。

02

协商缓存请求带条件头

浏览器可能带 If-None-Match,对应服务端之前给的 ETag;也可能带 If-Modified-Since,对应 Last-Modified。服务端用这些条件判断资源是否变化。

03

304 的响应体语义

304 表示 Not Modified,服务端没有必要再传完整实体内容。浏览器应该复用本地缓存里的 body,因此开发者看到页面正常显示,不代表 304 返回了同样的 body。

04

304 仍然可以带缓存相关响应头

304 响应可以更新 Cache-Control、ETag、Expires、Last-Modified 等元信息,浏览器会用它们刷新缓存策略。它省的是实体传输,不是完全没有响应头。

05

ETag 和 Last-Modified 的差异

Last-Modified 精度通常到秒,内容一秒内多次变化或只改元数据时可能不准。ETag 是资源版本标识,可以更精确,但需要服务端生成和比较。

06

开发工具里的常见误解

Network 面板可能展示从缓存恢复出来的内容预览,也可能显示 transferred 很小。那是浏览器组合本地缓存后的观察结果,不等于 304 响应体里真的传了完整资源。

易错点

  • 把 304 理解成服务端重新返回完整 body,只是状态码不同。
  • 把 no-cache 当成不缓存,分不清它和 no-store。
  • 只说浏览器缓存,不区分强缓存不发请求和协商缓存会发条件请求。
  • 认为 Last-Modified 足够精确,忽略 ETag 对秒级变化和内容版本判断的价值。

面试官追问

304 一定没有任何内容吗?

它通常没有新的实体响应体,但仍然会有状态行和响应头。浏览器使用本地缓存的实体内容完成渲染。

ETag 和 Last-Modified 谁优先?

同时存在时通常 If-None-Match/ETag 优先,因为它表达资源版本,比按时间判断更精确。

no-cache 是不是不缓存?

不是。no-cache 表示使用缓存前必须向服务端验证;完全不存储通常用 no-store。

强缓存命中和 304 的区别是什么?

强缓存命中不发网络请求;304 是发了条件请求,服务端确认未修改后让浏览器复用本地缓存。