我正在为Vue 3
应用程序设计一个具有分布式模块所有权的体系结构。模块系统将用插件表示(似乎是允许vuex
模块和vue-router
动态注入的最合适的解决方案(。每个这样的模块/插件都将由在独立的repos中工作的专门团队开发。我们不能使用每个插件npm
包的方法,因为部署过程也应该隔离,使用npm
方法,每次npm
包插件更新时,核心应用程序团队都必须重建应用程序。这意味着我们必须在运行时通过http
加载这样的插件/页面。
到目前为止,Markus Oberlehner的这种方法似乎是一种可行的方法——它使用自定义的基于Promise
的解决方案来解决webpack
的"缺失";在运行时加载外部url脚本";功能。虽然它与Vue 2
配合良好,但Vue 3
给出了VNode type: undefined
的错误。
上述文章提供了以下webpack
外部组件加载解决方案:
// src/utils/external-component.js
export default async function externalComponent(url) {
const name = url.split('/').reverse()[0].match(/^(.*?).umd/)[1];
if (window[name]) return window[name];
window[name] = new Promise((resolve, reject) => {
const script = document.createElement('script');
script.async = true;
script.addEventListener('load', () => {
resolve(window[name]);
});
script.addEventListener('error', () => {
reject(new Error(`Error loading ${url}`));
});
script.src = url;
document.head.appendChild(script);
});
return window[name];
}
但如上所述,Vue 3
defineAsyncComponent
机制不起作用。
// 2.x version WORKS
const oldAsyncComponent = () => externalComponent('http://some-external-script-url.js')
// 3.x version DOES NOT WORK
const asyncComponent = defineAsyncComponent(
() => externalComponent('http://some-external-script-url.js')
)
所以我有两个问题:
对于上述体系结构规范,是否有任何已知的更好的解决方案/建议?
有没有用
Vue 3
测试过的webpack
动态外部导入解决方案?
UPD:这里是小型复制回购
我们通过聊天一起解决了这个问题。
通过Vue 3 Vue-cli构建的组件依赖于全局范围内可用的Vue
。因此,为了呈现通过本文中描述的技术加载的组件,您需要将window.Vue
设置为对Vue
本身的引用。然后一切都按预期进行。
更新:
如果从vue/dist/vue.esm-bundler
导入vue并设置为global,则无需更改webpack/Vite配置,也无需从cdn加载vue。
import * as Vue from 'vue/dist/vue.esm-bundler';
window.Vue = Vue;
除了设置window.Vue
,还应该设置其他一些webpack或Vite配置,否则控制台中会出现一些错误:vue warn invalid vnode type symbol(static) (symbol)
Vue3+网络包:(https://github.com/vuejs/vue-next/issues/2913#issuecomment-753716888(
// index.html:
<script src="https://cdn.jsdelivr.net/npm/vue@3.0.4"></script>
// vue.config.js
configureWebpack: config => {
...
config.externals = { vue: 'Vue' }
...
}
Vue3+邀请:(https://github.com/crcong/vite-plugin-externals)
// vite.config.js
import { viteExternalsPlugin } from 'vite-plugin-externals'
export default {
plugins: [
viteExternalsPlugin({
vue: 'Vue'
}),
]
}