前端完成脚本、样式发布后,用户刷新却仍看到旧界面,最容易被误判成“服务器没有更新”。实际上,浏览器、网关代理和 CDN 可能分别持有一份旧副本;只要其中一层仍然命中旧对象,请求就不会回源取得新文件。下面按请求经过的顺序拆解缓存逻辑,并用响应头与请求记录逐层验证失效结果。
如果你正在选机器,或者想先把线路和配置跑通再谈长期方案,可以先看看这几家的线路说明和技术参数:digvps(全球云服务器),先看清带宽线路、流量策略和退款条款,再决定要不要迁。
浏览器先把旧资源留在本地
Cache-Control指令决定响应能否被缓存以及能够保留多久。对于带内容哈希指纹的脚本、样式和字体,可设置 max-age=31536000 并配合 immutable。文件名随内容变化后,请求 URL 也会变化,旧缓存便不会误用于新版本。入口 HTML 则适合使用短缓存或 no-cache,让浏览器定期重新验证,而不是永久记住旧页面。

文件名保持不变时,浏览器可能长期复用旧副本。此时可使用 ETag条件请求:浏览器携带 If-None-Match,服务端发现实体未变便返回 304,只更新响应头;内容改变则返回新的 200 响应和实体。需要留意,304 只表示当前缓存副本仍可复用,并不代表所有 CDN 节点都已取得新文件。
Service Worker缓存还会增加一层可编程存储。如果 Worker 采用 cache-first 策略,页面请求可能直接命中旧文件,甚至不会进入普通条件请求流程。更新 Worker 时,应清理不再使用的 Cache Storage,或在新版本激活后删除旧缓存键,否则常规的 CDN 刷新无法解决本地旧副本问题。
从CDN到源站逐层验证
代理和 CDN 位于浏览器之外。CDN 通常依据 URL、查询参数及部分请求头选择缓存键,同一路径在不同节点也可能保存不同副本。发布新文件后,除了确认回源策略,还要失效受影响的精确 URL 或路径。如果构建产物始终使用相同文件名,只刷新浏览器缓存没有意义,因为旧对象仍可能从 CDN 节点直接返回。

判断时不要只看页面是否变化,应在浏览器开发者工具的 Network 面板检查 Size、Age、Cache-Control 和 ETag;再开启 Disable cache 重新请求,对比两次响应内容与响应头。也可以用 curl 分别请求源站、代理和 CDN 入口,观察状态码、Age、ETag 与 Last-Modified,并确认请求是否真正到达上游。若响应携带 Age 且内容仍旧,应先检查 CDN;若浏览器显示来自磁盘缓存,则继续检查 Cache-Control 与 Service Worker。
版本化发布应贯穿整条链路:入口 HTML 使用短缓存或 no-cache,带哈希的资源使用长期缓存;发布时先上传全部哈希文件,再刷新对应路径,最后切换 HTML 引用。顺序错误会出现新 HTML 指向尚未上传的文件并造成短暂 404。还要避免代理、CDN和源站生成不同 ETag,或忽略压缩方式、来源及缓存键差异,否则表面返回 304,实体版本仍可能不一致。
排查期间,可以用 ServLlama 汇总多地请求结果,观察同一 URL 在不同区域返回的状态码和缓存头,辅助判断失效是否完成;最终仍应以源站、代理和 CDN 三处的实际响应为准。
Service Worker 缓存:旧版本可能藏在浏览器里
当网站使用 Service Worker 离线能力或精细化缓存策略时,即使服务器上的文件已经更新,浏览器也可能继续从本地缓存读取旧资源。Service Worker 会拦截页面请求,其缓存通常独立于普通 HTTP 缓存,因此单纯刷新页面,未必能拿到服务器上的新文件。
排查时先打开开发者工具的 Application 面板,检查是否存在多个 Worker 版本、waiting、activated 等状态,并查看 Cache Storage 中残留的旧条目。更新流程应确保新 Worker 安装完成后跳过等待阶段,在 activate 事件中删除旧缓存,并让新 Worker 接管当前页面。若使用 Workbox 等工具,还要确认预缓存清单是否随构建产物同步更新。
另一个常见问题是更新逻辑只监听页面首次加载。页面长时间不关闭时,新 Worker 即使已经安装,也可能一直处于 waiting 状态。可以在页面重新获得焦点时发送 skipWaiting 消息,再通过 clients.claim() 接管客户端;具体实现需要评估是否会造成新旧资源混用。

用版本化发布切断新旧资源纠缠
版本化发布的目标不是关闭缓存,而是让资源地址能够准确表达内容版本。构建时可在文件名中加入内容哈希,例如 app.8d31c0.js;也可以在入口文件中使用版本查询参数。每次发布使用新版本号或新指纹,浏览器就会把新地址视为独立资源,从而绕开旧缓存。
实践中宜采用长短结合的缓存策略:HTML 入口设置为不缓存或必须重新验证;带哈希的 JS、CSS、图片则允许长期缓存。如果文件没有内容指纹,不要直接设置一年强缓存,否则发布后极易继续命中旧文件。回滚时也应发布上一版本的完整资源清单,而不是只替换服务器上的单个文件。
可执行的发布后检查清单
第一步,用 curl 检查线上响应头与正文,确认源站返回的是新版本,并核对 CDN 节点是否存在旧内容。第二步,在 Network 面板中分别执行普通刷新和强制刷新,检查请求 URL、状态码、响应大小及 from disk cache、from memory cache 等来源。第三步,查看 Service Worker 生命周期和 Cache Storage,确认旧缓存已清理,新缓存键包含当前版本。第四步,用无痕窗口、不同浏览器或清理站点数据后复测,排除本地缓存干扰。最后,对登录态页面、CDN 缓存、移动端浏览器和旧版 Service Worker 分别验证,确保入口文件与所有静态资源使用同一版本。
如果排查后仍显示旧内容,应把“服务器文件是否更新”“响应缓存是否命中”“Service Worker 是否接管”“资源 URL 是否变化”分开验证。按照内容哈希核对线上文件,能够快速判断问题究竟来自发布流程,还是浏览器缓存策略。


喜欢
顶
难过
囧
围观
无聊





