我们有一个应用程序,我们在路线定义中使用动态导入语法,如下所示:
...
component: () => import('./components/SomeComponent'),
我们最近过渡到了 vite,自从切换以来,每当我们部署新版本的应用程序时,我们都会发现
TypeError: Failed to fetch dynamically imported module
。
根据this SO post,发生这种情况是因为文件的哈希在新部署上无效,但是当我们完全交付新版本时,为什么这些文件仍然被以前的哈希引用?
我还发现之前的问题遇到了同样的错误,并在其线程中找到了这个链接,其中讨论了rollup如何期望动态导入的特定语法:
// current
component: () => import('./components/SomeComponent')
// expected?
component: () => import('./components/SomeComponent.vue')
这可能是我们收到
Failed to fetch dynamically...
错误的原因吗?因为我的动态导入缺少文件扩展名?我有点困惑,因为即使没有文件扩展名,动态导入似乎仍然可以工作,只是我们在新部署上发现了错误。
但是为什么这些文件仍然被以前的哈希引用, 当我们完全交付新版本时?
动态模块的要点是并非所有代码都加载到浏览器中。 让我们看以下案例,您有一个带有 1 个动态模块的网站,通过单击按钮加载。
当你构建它时,你的文件应该如下所示:
index.html
assets/
-- index-abc123.js
-- dynamicModule-aaa111.js
因此,当用户打开您的网站时,他应该得到以下内容
index.html
assets/
-- index-abc123.js
请注意,用户尚未加载动态模块。
现在您将进行部署,并对 DynamicModule 文件进行轻微更改,您的文件名将更改为:
index.html
assets/
-- index-xxx345.js
-- dynamicModule-bbb222.js
现在,没有刷新浏览器的用户将单击应该导入动态模块的按钮。 将会发生的情况是,他的浏览器将尝试下载“dynamicModule-aaa111.js”,但该文件不再存在,并被“dynamicModule-bbb222.js”取代。 现在你会得到错误(无法获取动态导入的模块)
使用 Vue 3 动态导入组件的正确方法是使用
defineAsyncComponent()
,如下所述:https://vuejs.org/guide/components/async.html#basic-usage
<template>
<some-component></some-component>
<component :is="varComp"></component>
</template>
<script>
import { defineAsyncComponent } from 'vue'
export default {
components: { /* Directly in components */
SomeComponent: defineAsyncComponent(() => import('./components/SomeComponent.vue'))
},
computed: { /* or as computed property, e.g. with variable */
varComp() {
return defineAsyncComponent(() => import(`./components/SomeComponent${this.compx}.vue`))
}
}
}
</script>