原理
在版本号从 0.x 到 1.x 的升级时,内部原理有过调整,见下文。
早期 0.x 的原理
use-upgrade 利用现代 Web 构建系统中的 “chunk” 的概念(中文称作 “包、块”),以及 chunk 的文件哈希,实现对版本的识别和检验。
例如,无论使用 Vite 还是 Webpack,都会存在一个 “主 chunk” 的概念,它用于动态加载其它 “分 chunk”,并插入到 index.html 中。
插入 HTML 的标签示例:
<script defer="defer" src="/static/js/main.b5dd354f.js"></script>注意这里的文件 main.b5dd354f.js,其中 main 是 chunk 名,后面的 b5dd354f 为文件哈希。
网站的 index.html 中会存在大量的这种标签,但我们只需关注 “主 chunk” 的标签。
此时,只要项目中任一文件发生变动,其对应的 chunk 的内容和文件哈希就会一同变动;而主 chunk 会去加载其它 chunk,因此主 chunk 的内容和哈希也一定会发生变化。
因此,只需要持续检查比较 index.html 中的主 chunk 的文件哈希,即可得知网站是否有新版本发布,从而触发特定行为。
但是,不同的构建系统,输出的主 chunk 名也各不相同。
例如,有的叫 main(Webpack),有的叫 app(Vite),有的叫 main-app;因此,use-upgrade 内置了大多数构建工具的主 chunk 名,还配备了一套正则表达式用于正确提取主包文件哈希,以此来实现兼容性。
当前 1.x 的原理
目前,Next.js 新版已开始默认使用 Turbo 构建,构建产物已经没有 “主 chunk” 这一概念了,上述旧版方法已经无法检测到 Next.js 网站的更新。
除此之外,其它构建工具可能也会跟进,因此基于 “主 chunk” 的方法可能不再奏效。
因此,新版采用以下策略:不再尝试寻找 “主 chunk”,而是直接把整个 index.html 全文作为哈希函数的输入,计算出哈希值来作为 “版本号”,这便可以兼容几乎任何构建系统。
新版本这种方式带来的缺点是:在工具初始化时不能使用 DOM 读取到的 HTML 来记录 “当前版本号”,因为 DOM 已被修改,而是必须立即请求一次 index.html,这会增加少许网络开销。