Vue 3 外部 component/plugin 在运行时加载

Vue 3 external component/plugin loading in runtime

我正在为 Vue 3 应用程序设计一个基于分布式模块所有权的架构。模块系统将用插件表示(似乎是允许 vuex 模块和 vue-router 动态注入的最合适的解决方案)。每个这样的 module/plugin 都将由专门的团队在孤立的回购协议中开发。我们不能使用 npm package-per-plugin 方法,因为部署过程也应该被隔离,并且使用 npm 方法核心应用程序团队将不得不在每次 npm 包插件有更新时重建应用程序.这意味着我们必须在运行时通过 http.

加载这样的 plugins/pages

到目前为止,Markus Oberlehner 的 this approach 似乎是某种方式 - 它使用基于自定义 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')
)

所以我有两个问题:

  1. 是否有更好的solutions/suggestions以上架构规范?

  2. 是否有 webpack 动态外部导入解决方案经过 Vue 3 测试?

UPD:这里是小reproduction repo

我们通过聊天一起解决了这个问题。

通过 Vue 3 vue-cli 构建的组件依赖于 Vue 在全局范围内可用。因此,为了渲染通过我文章中描述的技术加载的组件,您需要将 window.Vue 设置为对 Vue 本身的引用。然后一切正常。

更新:

如果从vue/dist/vue.esm-bundler引入vue并设置为全局,则无需更改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 + webpack:(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 + vite:(https://github.com/crcong/vite-plugin-externals)

// vite.config.js
import { viteExternalsPlugin } from 'vite-plugin-externals'

export default {
  plugins: [
    viteExternalsPlugin({
      vue: 'Vue'
    }),
  ]
}