1. 这个错误是怎么触发的
假设你的网站域名是 www.xxx.com,你有三个路由 /home /about /dashboard
用户A 第一次访问 www.xxx.com/home 的时候,浏览器会自动缓存 /home 所需要的静态资源,然后访问 www.xxx.com/about,浏览器会再次缓存 /about 所需要的静态资源。
这时,我们重新修改代码,并发布上线。用户A 本地有 /home. /about 缓存,所以切换这两个页面不会出错,然而 用户A 并没有访问过 /dashboard,所以 /dashboard 页面的静态资源并没有加载且缓存。
所以当 用户A 在 /home 路由下访问 /dashboard 的时候,因为当前路由 /home 下使用的还是浏览器的缓存,所以 访问 /dashboard 用的也是旧的资源链接,进而引发出了报错 Failed to fetch dynamically imported。如果你的 nginx 配置了 访问不到资源就跳转到 index.html 那么还有可能会报错 Failed to load module script
2. 如何解决这个问题
这个问题现阶段其实并没有一个比较官方的解决方法
首先我们知道,用户在不刷新页面的情况下,访问的一定是缓存的代码。因为前端的资源都是静态的,所以我们必须找到一个动态的内容去让用户手动触发更新,或者通过动态内容替用户更新。
很明显,动态的内容最简单的方案就是后台的接口,后台访问前端当前代码的版本。我们每隔一段时间去请求后台,当后台返回的版本和当前版本不一致的时候,就弹出一个按钮,或者直接帮用户刷新页面,那么前端的资源就更新为最新页面了。
不通过后台的方案就是发布的时候,你在 public 文件夹里存一个 version.txt,每次发布的时候改一下里边的内容。因为 public 文件发布后是不会加 hash 的,所以请求 /version.txt 的时候不能使用缓存 Cache-Control: no-store。
其实当我们打开 vue、react、vite 官网时,如果长时间不退出且不刷新页面,右下角就会弹出一个提示框,内容有更新,当我们点击这个按钮的时候,页面就会刷新一次,应该(我没去验证,猜的)也是一样的方法去实现内容更新的。