Files
TrueGrowth/docs/STALE_ENTRY_AND_HASH_ASSET_LESSONS.md

5.5 KiB
Raw Blame History

旧入口与悬空 Hash 资源经验总结

更新日期2026-04-22

现象

线上会出现这样的请求:

  • https://opentu.ai/assets/index-Bfl2zVkU.js

但当前本地构建里:

  • 没有这个文件
  • 当前 version.json 已经是新版本
  • 当前 index.html 里写死的首屏入口也已经是新的 hash

最终表现是:

  • 线上请求一个本地根本不存在的旧 hash 资源
  • 资源 404
  • 页面继续卡在半启动状态

先说结论

这类问题,几乎不可能是“当前构建自己算错了入口名”
更常见的根因是:线上仍有旧入口链路在生效

也就是说,请求旧 hash 资源,通常不是新包生成出来的,而是以下某一层还没切干净:

  • index.html
  • Service Worker
  • 旧缓存清单
  • 非原子部署导致的“旧入口 + 新 assets”错配

这次排查得到的判断依据

本地核对时,如果同时满足下面几条,就可以基本排除“当前构建有问题”:

如果这五条都成立,而线上还在请求旧 hash那么就说明

问题发生在线上入口一致性,不在当前本地构建。

根因分类

1. 旧 HTML 还在返回

最常见。

例如:

  • 浏览器拿到的是旧版 index.html
  • 这个旧 HTML 里仍然引用 index-Bfl2zVkU.js
  • 但服务器上的 assets 已经切成了新版本
  • 旧 hash 文件被删掉或覆盖,于是直接 404

经验:

  • 只看服务器目录里有没有新文件,不够
  • 一定要看用户真正拿到的 index.html 是不是新版本

2. 旧 SW 还在接管页面

即使 HTML 是新的,也可能出现:

  • 浏览器仍被旧 Service Worker 控制
  • 旧 SW 里缓存了旧入口或旧资源映射
  • 结果页面继续请求已经失效的 hash 文件

经验:

  • “页面刷新了”不等于“SW 已切到新版本”
  • 尤其是首屏加载链路里SW 的生命周期和 HTML 更新不是同一步完成的

3. 部署不是原子切换

这类问题本质上是版本错配。

错误顺序通常像这样:

  1. 先清理或覆盖旧 assets
  2. 用户手里仍有旧 HTML / 旧 SW
  3. 旧入口继续请求旧 hash
  4. 服务器上该文件已不存在
  5. 直接悬空 404

经验:

  • hash 资源不是“删旧文件就完事”
  • 只要线上还有旧入口引用它,就不能立刻清掉

这次最值得固化的规则

1. 排查这类问题,先分清“请求是谁发起的”

要先回答两个问题:

  • 这个旧 hash 是当前构建产物里写进去的吗?
  • 还是某个旧 HTML / 旧 SW / 旧缓存发起的?

如果不先分层,排查很容易跑偏,最后误以为是“打包器有 bug”。

2. 不要把“资源 404”直接归因到构建

当线上请求本地不存在的旧 hash 时,第一反应不该是:

  • 当前构建产物生成错了

更应该优先怀疑:

  • 入口链路未完全切换
  • 缓存未清干净
  • 部署顺序不安全

3. HTML、SW、assets 必须按“版本一致性”设计部署

前端静态站不是只部署 assets 就行。

真正要保证一致性的至少有三类文件:

  • index.html
  • sw.js 与相关缓存清单
  • assets/*.js / assets/*.css

只要它们切换不是同一版本视角,就会出现旧入口引用新资源或新入口引用旧缓存的问题。

推荐的排障顺序

第一步:确认本地产物有没有这个旧 hash

查三处:

  • 打包后的 index.html
  • 预缓存清单
  • dist/assets

如果都没有,基本可以判断不是当前构建写进去的。

第二步:确认线上返回的 index.html 是谁

重点看:

  • app-version
  • 首屏 module 入口脚本
  • 缓存头是否过久

第三步:确认线上 SW 是否仍是旧版本

重点看:

  • sw.js 内容或版本标识
  • 预缓存清单版本
  • 是否存在旧 cache key

第四步:回看部署顺序

重点确认:

  • 是否先删旧 assets
  • 是否旧 HTML 仍可能被 CDN / 浏览器缓存命中
  • 是否给旧入口留了过短的存活窗口

后续应该怎么设计更稳

1. 部署要尽量原子

推荐原则:

  • 新 HTML、生效中的 SW、对应 assets 应该成套发布
  • 不要出现“新旧资源混挂”的过渡窗口

2. 不要过早清理旧 hash 资源

更稳的策略是:

  • 允许旧版本 hash 资源保留一个短暂过渡期
  • 等确认旧 HTML / 旧 SW 基本退出后再清理

一句话:
hash 资源可以延迟清理,首屏入口一致性不能冒险。

3. SW 升级链路要可观测

至少要能看出:

  • 当前页面由哪个 SW 控制
  • 当前 cache 清单属于哪个版本
  • 当前启动入口来自 HTML、SW 还是缓存恢复

否则这类问题到了线上基本只能猜。

一句话总结

线上请求“本地构建里根本不存在的旧 hash 资源”,通常不是当前构建错了,而是:

  • 旧 HTML 还在返回
  • 旧 SW 还在接管
  • 或部署不是原子切换

真正该修的,不只是资源路径,而是入口一致性与部署时序🔧