打开浏览器开发者工具的 Network 面板,页面加载时一堆请求里夹着灰色的几行,Status 显示 304,第一次见到容易以为是出错了。恰恰相反,304状态码是好事:它表示资源没变,浏览器直接用本地缓存的版本,服务器不用把文件再传一遍,加载快了,流量也省了。

完整流程是这样:浏览器第一次请求一张 logo 图片,服务器返回 200 和文件内容,同时带上 Last-Modified 最后修改时间或 ETag 内容指纹,ETag 多数框架和 nginx 会默认生成。下次请求,浏览器自动带上 If-Modified-Since 或 If-None-Match 问服务器:我缓存的这份还是新的吗?服务器一比对没变,回一个 304,不带正文,浏览器拿本地那份渲染;确实改了,则返回 200 和新内容。

304 和强缓存的区别

Network 面板里还会见到另一类:Size 一列直接写着 disk cache 或 memory cache,一个请求都没发出去,这叫强缓存,由 Cache-Control 或 Expires 控制,后者精确到具体时间点,前者用 max-age=3600 这类秒数表示,现在主流用 Cache-Control。强缓存比 304 更省,304 好歹还发了一次请求问话,强缓存连问都不问。两者是配合关系:强缓存过期后,再走协商缓存,也就是 304 这套流程。304 的响应体为空,抓包工具里看到它的响应都很小。

什么情况要留意

  • 调试页面想强制拿最新文件,按 Ctrl+F5 强制刷新,会跳过缓存直接要 200。
  • 自己写的静态服务没返回 Last-Modified 和 ETag,浏览器每次只能拉全量 200,白白费流量,配上这两个响应头就能吃到协商缓存。
  • 文件在一秒内被改了两次,Last-Modified 只精确到秒,可能感知不到,这类场景用 ETag 更稳。

判断标准一句话:304 多不是问题,是缓存在正常工作;该更新的时候资源一直是 304,先怀疑文件指纹或修改时间没变,再去查服务器配置。