订阅决策
页面看起来没更新,未必是内容没有变化:新鲜度、验证请求与资源版本怎么核对
同一地址显示旧内容,可能来自浏览器私有缓存、共享缓存、条件验证、页面快照或脚本管理的缓存。本文以 IETF 缓存标准和 Mozilla 浏览器文档为依据,说明如何从响应新鲜度、验证器与资源版本判断差异,而不把刷新结果当成唯一证据。
同一地址不一定对应同一副本
手机显示旧标题,电脑已经看到新标题。两台设备都访问同一个地址,也都没有报错。差异并不自动证明某台设备异常,更不能据此认定内容被改写。
HTTP缓存的目的,是让先前收到的响应在条件合适时再次使用。浏览器可保存私有副本,访问路径中也可能有共享缓存。服务方还可能使用反向代理、CDN或脚本管理的缓存。
这些层保存副本的时间不同,请求条件也不同。核对内容差异时,先问现在看到的是哪一层的哪一版,而不是把刷新按钮当成唯一答案。
新鲜副本可以不联系原站
RFC 9111规定,已存响应若匹配当前请求,且仍处于新鲜期,就可以直接重用。这样能减少网络等待,也能减少服务器重复处理。
新鲜期通常由Cache-Control中的max-age等信息决定。副本年龄小于允许时长,缓存不必为了每次访问重新询问原站。
因此,原站内容刚变化后,某台设备短时间仍看到旧内容,可能只是它持有的副本仍新鲜。这个现象本身不说明更新失败。
Age字段可提供从原站生成或验证响应后经过的估计秒数。RFC也提醒,缺少Age不能反推一定联系了原站,所以它是证据之一,不是唯一判据。
过期并不等于副本被删除
副本超过新鲜寿命后会变成陈旧。陈旧是使用条件改变,不是文件自动消失。缓存仍可保留正文,并向下一站验证它是否还能继续使用。
若响应带有no-cache,含义也不是禁止存储。它要求缓存再次使用前先完成验证。真正表达不应有意存储的是no-store,两者处理的问题不同。

MDN进一步指出,后来收到no-store不会自动清除同一地址已经保存的旧副本。把指令名称当成清理按钮,容易误判实际状态。
must-revalidate则限制陈旧副本的重用。RFC要求,在该指令适用时,缓存成功验证前不能把陈旧响应用于新请求。
验证可以避免重传正文
常见验证器是ETag与Last-Modified。缓存把已有副本的标识放入If-None-Match,或把修改时间放入If-Modified-Since,请下一站比较当前表示。
若内容未变化,服务端可返回304。这个状态没有正文,因为浏览器已经有可继续使用的副本。304不是没有检查,而是检查后确认无需重传。
若标识不同,服务端通常返回200和新正文。此时应同时观察状态码与验证器,而不是只看画面是否像旧版。
ETag可代表某个资源版本,但生成方式由服务端决定。修改时间也可能受时间精度限制。可靠判断需要看它们是否随真实内容变化,而不是只确认字段存在。
同一URL也可能有多个缓存条目
缓存通常以地址为基础选择副本,但Vary会把指定的请求字段纳入匹配。语言、压缩编码或其他声明条件不同,同一URL可以对应不同条目。
RFC 9111要求,Vary列出的字段若与保存副本时不一致,就不能未经验证直接重用该响应。手机与电脑发送的请求条件不完全相同,因而可能命中不同副本。
这不表示Vary能解释所有差异。登录状态、应用脚本和个性化数据可能另有规则。发现同址不同内容时,需要辨明它是公共页面还是与用户状态有关。
公共标题或说明出现差异,可比较响应头与正文。私人页面则不应把另一位使用者的画面当成标准副本。
刷新只改变部分请求路径
MDN说明,普通刷新常会发送max-age=0,并带上已有的ETag或修改时间进行验证。若内容没有变化,仍可收到304并使用本地正文。
后退与前进导航可能恢复页面快照,而不是按普通导航重新请求。即使响应写了no-cache,也不能保证历史导航每次都验证。
强制刷新在不同浏览器中的细节也不完全相同。它可以帮助对照,却不等于绕过所有共享缓存、页面快照与应用脚本。
较稳的比较是保存完整地址,分别进行普通导航、刷新和新会话访问。每次记录状态码、Age、Cache-Control、ETag与最终画面,才能知道路径在哪里分开。
脚本缓存有自己的更新规则
部分网站使用Service Worker与Cache API保存资源。MDN指出,Cache对象中的条目不会自动更新,也不会因时间到期自动删除。
脚本必须明确决定何时加入新版、删除旧版或切换缓存名称。更重要的是,Cache API不遵循HTTP缓存头。只调整HTTP层的Cache-Control,不一定改变脚本选中的资源。
这解释了一个边界:清理或验证浏览器HTTP缓存后,页面仍可能由脚本缓存返回旧资源。只有网站确实使用这项接口时,这个解释才成立。
检查时可观察是否注册了Service Worker,以及资源回应来自哪里。不要在没有证据时把所有差异都归给脚本缓存。
资源版本要和HTML一起看
脚本、样式和图片适合使用带版本号或内容哈希的地址。内容改变时地址也改变,缓存便会把它视为新条目,而旧版本仍可安全保留较长时间。

MDN称这种做法为改变资源URL。主HTML通常不能用同一方式不断换地址,因此更适合使用验证器保持可更新性。
如果HTML已指向新版脚本,而某台设备仍拿到旧HTML,它就会继续请求旧资源地址。若HTML是新版但资源地址没有变化,旧资产又可能被直接重用。
所以画面差异不能只查主文档。需要把HTML、脚本、样式和关键图片的地址与版本标识放在同一记录中。
用证据顺序核对差异
第一项记录完整地址与访问时间。第二项记录设备、浏览器、普通导航或历史返回。第三项查看主文档的状态码、Age、Cache-Control、ETag和Last-Modified。
第四项核对Vary与请求条件。第五项比较HTML引用的资源地址。第六项确认是否存在Service Worker或Cache API管理的副本。
RFC 9111允许仍新鲜且请求匹配的已存响应不经验证直接重用。ETag或Last-Modified可让陈旧副本通过条件请求验证,未变化时返回304并继续使用原正文。
设备持有不同年龄、Vary条件或脚本缓存版本的副本,因此同一地址可以在同一时刻显示不同内容。普通导航可能直接重用新鲜副本,刷新通常触发验证,而新会话仍可能经过共享缓存或脚本缓存。
缺少Age不证明联系了原站,刷新不保证绕过所有层,Cache API也不遵循HTTP缓存头。确认这些边界后,内容差异才能从感觉变成可复查的路径证据。
用一组对照找出分岔点
假设手机显示标题A,电脑显示标题B。复制完整地址后,辨别两边有没有跳到不同路径,或附带不同参数。地址若已不同,问题属于导航或资源版本,不宜继续当成同一缓存条目比较。
地址相同后,分别保存主文档的状态码和响应头。手机若收到带较小Age的200,电脑收到另一个ETag的200,说明两条路径持有的表示可能不同。此时应查Vary与请求字段,而不是立即删除资料。
若手机刷新得到304,表示它确实完成了条件验证,下一站仍认可原副本。若电脑得到200和不同ETag,则它取得了另一表示。两个结果可以同时符合协议,关键在于它们验证的请求条件是否相同。
再开启新会话访问。新会话没有原来的浏览器私有副本,却仍可能经过共享缓存。若画面与旧会话不同,差异更接近浏览器存储;若仍相同,则要继续检查共享层和原站选择逻辑。
不要把清理动作当成诊断证据
删除全部浏览数据会抹掉对照所需的旧副本、Cookie和访问状态。画面恢复后,也难以判断真正改变的是HTTP缓存、登录状态、页面快照还是脚本缓存。
更小的动作是先保存证据,再只开新会话或换一个未访问过的浏览器。这样旧环境仍可重现,新的请求又能提供独立参照。
若确认只有一个静态资源版本不一致,可比较该资源地址与ETag。若主文档本身不同,则先处理主文档的新鲜度和验证。把层次分开,比同时清理所有内容更容易定位。
最终记录应允许另一位读者复查:哪台设备、哪个完整地址、哪种访问方式、什么状态码和响应头、页面显示哪一版。缺少这些条件时,只能描述现象,不能宣称唯一原因。
资料来源
- IETF / RFC Editor:《RFC 9111: HTTP Caching》,发布或更新于 2022-06-01
- Mozilla MDN:《HTTP caching》,发布或更新于 2026-07-14
- Mozilla MDN:《Cache API interface reference》,发布或更新于 2025-07-28