错误分析
这个报错的来源的意思是远程模块导入失败
通常是因为网页处于活动状态时服务器资源更新了
然后html中引用的.js文件找不到了
这篇文章解决的就是这种通常情况
参考这两篇文章
stackoverflow.com/questions/6…
juejin.cn/post/722544…
基本思路
在每次打包时 同时在服务端和网页上设置时间戳
如果发生了这个异常 就对比服务端和当前页面的时间戳是否相同 不同就刷新网页
具体做法
项目是vue,vue-router,vite的
考虑把时间戳直接打在index.html上 并在router.onError内捕获
打包时打时间戳
// vite.config.js
plugins: [
{
// 为生成的html加时间戳
name: 'html-timestamp',
transformIndexHtml (html) {
return html.replace(
/<html.*?>/,
str => str.replace('html', `html data-ts="${Date.now()}" `),
)
},
},
],
捕获异常
// @/router/index.js
router.onError((error, to, from) => {
if (
process.env.NODE_ENV === 'production' &&
error.message.includes('Failed to fetch dynamically imported module')
) {
fetch('')
.then(res => res.text())
.then(html => {
const currentTs = document.querySelector('html').dataset.ts
if (!html.includes(`data-ts="${currentTs}"`)) {
const baseUrl = location.href.slice(0, -from.fullPath.length)
window.open(baseUrl + to.fullPath, '_self')
}
})
}
})
用fetch获取最新的html 与当前网页中的进行对比
这里不需要担心缓存的问题 响应头content-type为text/html的不会被浏览器自动缓存
to.fullPath前面加了个baseUrl 是因为存在多入口项目
比如本地的url是 http://127.0.0.0/test
生产环境是 http://xxx/client/test
要把http://xxx/client取出来拼接