Vue 3在运行时加载外部组件/插件



我正在为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 3defineAsyncComponent机制不起作用。

// 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')
)

所以我有两个问题:

  1. 对于上述体系结构规范,是否有任何已知的更好的解决方案/建议?

  2. 有没有用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'
}),
]
}

最新更新