【问题标题】:Vue 3 external component/plugin loading in runtimeVue 3 外部组件/插件在运行时加载
【发布时间】:2020-12-14 07:14:38
【问题描述】:

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

到目前为止,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. 对于上述架构规范是否有任何已知的更好的解决方案/建议?

  2. 有没有用Vue 3 测试过的有效webpack 动态外部导入解决方案?

UPD:这里是小号reproduction repo

【问题讨论】:

  • 你好 Denys,这里是 Markus。你能提供一个复制的 Git repo 吗?刚刚用 Vue 3 对其进行了测试,它对我有用。
  • 嗨@moriartie,我在票证描述中添加了回购链接。感谢您愿意看看)
  • @markoffden 你愿意加入chat.stackoverflow.com/rooms/240683/vue-external-components 聊天并在某个时候帮助我吗?我正在尝试走类似的路线,但遇到了问题。
  • @DavidTorrey 抱歉,当时是在远离笔记本电脑的纽约假期 :) 我可以补充一点,那时我们选择不更新到 Vue 3。我们还使用了 single-spa 包。然后我离开了这个项目,所以没有更多可以分享的,AFAIK 团队对上述方法很满意。

标签: vue.js webpack vue-cli vuejs3


【解决方案1】:

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

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

【讨论】:

  • 请查看这个后续问题,关于在加载组件的 Vue 组件中动态包含这些外部预编译 .js 文件之一的 url。干杯。 stackoverflow.com/questions/64584561/…
  • @moriartie 是否有工作的 git repo 示例?我已经设置了 window.Vue,但是我这辈子仍然有各种各样的错误
  • @DavidTorrey 不,没有回购。但现在我强烈建议研究 webpack 模块联合以获取类似的功能!
  • @moriartie 感谢您的关注。它有点工作(我可以让它加载)但交互性似乎不起作用(例如 v-bind 和 v-model,即使只是在远程组件本身内),所以我需要找到一个替代方案思考。我想要完成的事情可能不可行
【解决方案2】:

更新:

如果 import vue from vue/dist/vue.esm-bundler 并设置为 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 + 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'
    }),
  ]
}

【讨论】:

    猜你喜欢
    • 2018-01-18
    • 1970-01-01
    • 2018-03-13
    • 2020-09-14
    • 2017-03-29
    • 2021-05-08
    • 1970-01-01
    • 2019-07-02
    • 2022-12-08
    相关资源
    最近更新 更多