问题描述
在Web前端应用中,为了减小文件大小,我使用了代码拆分(code splitting)技术。应用部署在CDN上,大部分时间都可以正常工作。然而,当我们随时更新项目时,会出现一个问题。
假设我们的项目由以下文件组成:
– index.html
– main.1ef1a.js
(其中1ef1a
是内容哈希)
– on-demand.bce31.js
index.html
导入了 main.[content-hash].js
,而 main.[content-hash].js
则在需要时动态加载 on-demand.bce31.js
。
问题出现在用户在我们进行更新时加载页面,此时用户获取了 index.html
和 main.1ef1a.js
,并且浏览器对它们进行了缓存。随后我们进行了更新,替换了这些文件并清空了CDN缓存,更新后的文件如下:
– 现在的 index.html
导入了新版本的 main.js
– main.2a3db.js
– on-demand.5231f.js
然后,用户执行了触发加载 on-demand.js
的操作,但由于其 main.js
仍然是旧版本,因此请求了 on-demand.bce31.js
,然而该文件已经不存在,从而导致页面崩溃。
用户尝试刷新页面,但浏览器仍然提供了缓存的 index.html
和 main.js
,使用户无法摆脱这个循环。我们不能指望用户具备清除缓存并强制刷新的知识,所以我们得到的只是感到失望的用户,他们会认为我们的网站很糟糕。
我认为代码拆分和CDN都是广泛使用的技术,应该有一些解决方案,只是我还没有找到。那么,有什么好的解决方案呢?
解决方案
请注意以下操作可能受到版本差异和特定环境的影响,使用前请谨慎测试。
解决方案1:更新策略优化
主要问题在于您在部署新的构建版本时清空了CDN缓存,从而导致正在进行中的请求被中断。为了解决这个问题,您可以优化您的更新策略:
- 保留旧版本文件:在部署新的构建版本时,不要立即清空旧版本的文件,而是将新版本的文件添加进去。这样,即使用户访问旧版本的页面,仍然可以下载旧版本的文件,直到缓存过期。用户会在缓存过期时获取新版本的首页,从而引用新版本的文件。
解决方案2:使用文件哈希
在构建和发布新版本时,确保生成唯一的文件名,以避免覆盖不同内容的文件。您可以通过对文件内容计算哈希并将其作为文件名的一部分来实现。这样,即使用户加载了旧版本的页面,他们也会下载正确版本的文件。
解决方案3:自动刷新
在页面上添加自动刷新的机制,使得一旦您部署了新的构建版本,用户的页面会自动刷新,从而获取最新的文件。
总结
在使用代码拆分和CDN时,为了避免用户在更新时遇到问题,您可以优化更新策略、使用唯一的文件名以及考虑添加自动刷新机制。这样可以确保用户始终获取正确版本的文件,从而提供更好的用户体验。