@
neoblackcap @
opengps @
dcsuibian @
ryougifujino 我觉得大家都把这个功能实现想复杂了,不必用 websocket ,也不搞热更新,也不用其他同事配合,只要前端一个人能就能完成。帖子开头和 #7 楼也把前提说清楚了,这个方案是针对 to b 的,比如自动售货机,肯定有一段空闲时用户不在使用的。
其实有些人已经说到点子上了,自动更新版本肯定得用 js 执行 location.reload(),肯定得增加版本号(但这个版本号不用是 x.y.z 的形式,应为要额外为版本判断写代码);
我昨晚也实验了一下,因为我目前就在做自动收银机的项目,大家看看这个方案咋样:
-- 给 index.html 文件设置 http 缓存响应头 no-store 或者 no-cache ,保证每次拿到的 index.html 文件都是最新的
-- 给 js/css/img 等其他资源设置一个比较长时间的缓存响应头,比如一年。
-- 每次打包都给 index.html 文件中的 html 元素增加当前打包的时间戳,打包后的 <html /> 元素就变成了 <html data-timestamp="..." />, 这个时间戳其实就是版本号,因为我们只需要探测最新版本
-- 我在全局增加一个每隔几分钟获取 index.html 的请求,fetch('/').then(response => const bodyString = response.text()), 拿到 document 字符串,再用正则解析出 data-timestamp 去和 document.documentElement.dataset.timestamp 对比,如果比这个值大,就是最新版代码,然后再检测用户没操作多少秒执行 location.reload(), 这样就更新代码了
再说下 location.reload() 的执行前怎么才能不破坏用户体验
- 如果是自动售卖机,我会给个 3 秒倒计时的弹窗,有文案提示系统检测到版本更新,即将更新,倒计时结束后就 reload
- 如果是后台管理,我会像 vscode 每次更新一样,右下角给个提示,让用户自己觉得是否更新
这个方案我昨天以为能最小代价更新代码,比如我只更新了一个 js 文件,我就希望刷新后除了这个 js 文件其他文件都能走缓存;其实不是,因为打包工具(比如 rollup )不止会给该 js 更新 hash ,所有引入该 js 文件的文件名中的 hash 都会改变,这就导致该 js 的祖先文件都不能走缓存了,现在服务器都是按请求收费的,这样肯定不划算,但目前没办法。
不过如果你把外部库( node_modules )都单独分割出来,这个 js 文件(一般称为 vendor )基本是不变的,所以我觉得即使是在弱网环境下,reload 也不会太慢。
不知道大家咋看?