页面刷新以后,浏览器一定会把所有内容重新下载一遍吗?先别急着看状态码。更有用的起点,是问这份内容允许多久不变,以及变化后如何被发现。

01 / 能直接用,就少一次往返

Cache-Control: max-age=600 表示响应可以在规定的新鲜期内被复用。这里的 600 是秒数;缓存会结合响应年龄判断,而不是每次打开页面都重新计时。对于短时间内稳定的公开内容,这能省下网络往返。

先给资源分组,再选缓存策略:入口 HTML 经常引用新的资源版本;带内容哈希的 CSS 文件,在同一个 URL 下通常不应该再改变。两者不必使用同一套规则。

02 / 过期以后,先问有没有变

缓存过期不代表必须丢弃。服务器可以给响应一个 ETag;下次浏览器带着它发出条件请求。资源未变时,服务器返回 304 Not Modified,浏览器继续使用已有内容。

HTTP · 一次条件请求的示意
GET /notes/ HTTP/1.1
If-None-Match: "notes-v3"

HTTP/1.1 304 Not Modified
ETag: "notes-v3"
Cache-Control: no-cache

这仍然发生了一次网络请求,只是不用重新传输正文。因此,看到 304 时,可以继续检查耗时发生在连接、等待响应,还是其他资源的加载上。

03 / 两个相似名字,不同的约定

先分清是否存储,再考虑是否复用
指令主要含义
no-cache允许存储;复用这个 HTTP 响应前需要重新验证。
no-store要求缓存不要存储这次响应。
private允许浏览器等私有缓存保存,禁止共享缓存保存。

不要因为名字里有 no-cache,就把它理解成“完全不缓存”。也不要为了省事,给包含个人信息的响应套上长时间的公开缓存策略。

继续阅读

MDN · HTTP caching

本文用简化的请求说明概念;浏览器历史导航等机制还需要结合具体场景判断。