1.问题描述
vue + vite项目:有时跳转页面会卡住,但刷新一下页面又恢复正常,控制台信息如下:
TypeError: Failed to fetch dynamically imported module: xxx
2.信息收集
用户端复现了问题,从现场获取到控制台日志:
3.问题分析
从报错来看,动态加载模块失败
单独访问module链接,服务端响应404
查看服务器文件,发现服务端文件,与请求文件的hash不一样, 也就是说服务端文件发生了变更,只有一种情况下,服务端文件会发生变更:有版本发布,并且文件代码有更新,才会导致文件hash值变化。
问题推测:用户在发布版本之前已经打开效能管理平台,在版本发布之后,用户跳转有代码更新的页面便会失败
问题证明:询问用户是在什么时候打开的页面,并通过对比鲸云版本发布时间点,对比结果符合上面的猜想,并通过自定义版本号,在测试环境成功复现问题。
到这里,问题基本确定。
4.问题解决
接下来是如何解决这个问题
问题的本质是:版本发布后,某些资源的链接可能发生变化,如果有用户正打开版本更新前的页面,那么此时跳转页面便有可能失败
问题解决思路:在版本发生变更时,自动重载页面,如此便会获得最新的资源链接
实现思路:
- 首先需要标记版本号:版本号已经存在于
Jenkinsfile
,不过该文件与js
文件分离,需要从其中读取出来 - 本质上
js
文件都会下发到客户端,在客户端执行,但浏览器又存在js
缓存,因此不能从js
变量读取version
,读取到的都是发布前的版本号 - 可以每次进行代码构建时创建一个
version.txt
,将版本号写入该文件,并且将该文件在服务端暴露,并服务端设置txt
文件不缓存,前端可通过http
请求,访问version.txt
, 则可读取到最新的版本号 - 读取服务端版本号时机选择:有两种方式,一是定时轮询(确定是比较耗费资源),二是用户点击新链接时查询版本号(可在路由守卫中实现,缺点是会影响页面跳转速度)
- 由于上面问题是一个较小概率事件,不应该对解决该问题花费过多的代价
基于方案二,能否在不影响跳转速度的同时,获取最新版本号?可以,也有两种方法:1.使用异步方式获取版本号,2.使用web worker
获取版本号
- 异步方式缺陷:出现异常可能会影响到主线程,异步代码会在同步代码执行完之后进行,版本检测速度会有影响
- 使用
web worker
可以解决异步的缺陷,web worker
工作在单独的线程,如果worker出现异常不会影响主线程,在多核CPU
下worker
与主线程并行执行,速度会更快, - 现代浏览器对
web worker
的支持也比较不错: