vue3 微前端项目 主项目中的公共组件如何下发到子项目中使用?

我现在的做法是在主项目中将组件放到window中

import { cloneDeep } from 'lodash';
import SCDrawer from '/@/components/SC/SCDrawer.vue'

window.MicroFrontends = {
    SCComponents: {
        SCDrawer: cloneDeep(SCDrawer)
    },
    
}

子项目在window中获取 并且注册到app

export const SCComponents = (app) => {
    const SCComponents = window.MicroFrontends.SCComponents
    app.component('SCDrawer', SCComponents.SCDrawer);
}

// main.ts
const app = createApp(App);
SCComponents(app)

但是使用过程中发现如果组件中有插槽slot

<template>
    <div>
        <slot></slot>
    </div>
</template>

那么子组建使用时会报错 Cannot read properties of null (reading 'isCE')
image.png
我看网上说是vue版本不一致导致的,但是我检查了我的主项目与子项目的vue版本是一样的
请问大佬们 有没有什么解决的方法 或者有其他主子应用共享组件的方法也行

阅读 746
avatarAI BotBETA

在 Vue 3 中,直接将 Vue 组件实例放入 window 对象并尝试在另一个项目中复用,尤其是在微前端架构中,可能会遇到兼容性和状态管理的问题,特别是涉及到插槽(slots)和组件实例的共享时。由于 Vue 组件实例通常依赖于其创建的上下文(如 Vue 应用实例),直接跨应用共享可能会导致不可预见的行为。

解决方案

1. 使用组件库

将公共组件打包成一个独立的 npm 包或私有库,然后在主项目和子项目中分别安装和引用。这样可以确保组件的独立性和版本一致性。

步骤

  • 使用 Vue CLI 或其他工具创建一个新的库项目。
  • 将公共组件放入库中。
  • 构建库并发布到 npm(或私有仓库)。
  • 在主项目和子项目中安装该库。

2. 使用 Webpack 的 externals

如果你不想发布到 npm,但想从另一个项目中引用打包后的组件,可以使用 Webpack 的 externals 配置来引入外部资源。

主项目(构建组件库):

  • 使用 Webpack 打包组件库,并输出到可访问的 URL 或本地文件。

子项目(引用打包后的组件库):

  • 在 Webpack 配置中设置 externals,指向主项目中打包的组件库。
  • 在项目中通过 <script> 标签或模块导入方式引入打包后的 JS 文件。

3. 使用模块联邦(Module Federation)

如果你使用的是 Webpack,可以考虑使用模块联邦(Module Federation)来实现微前端之间的代码共享。

步骤

  • 在主项目中配置 Webpack 的 Module Federation 插件,暴露需要共享的组件。
  • 在子项目中配置 Webpack,以便从主项目中加载这些暴露的组件。

这种方法允许你在不直接暴露全局对象的情况下,在多个应用之间共享代码。

示例:Webpack Module Federation

主项目配置(暴露组件):

// webpack.config.js
module.exports = {
  // ...
  plugins: [
    new ModuleFederationPlugin({
      name: "HostApp",
      remotes: {},
      exposes: {
        "./SCDrawer": "./path/to/SCDrawer.vue"
      },
      shared: ["vue"]
    })
  ]
};

子项目配置(加载组件):

// webpack.config.js
module.exports = {
  // ...
  plugins: [
    new ModuleFederationPlugin({
      name: "RemoteApp",
      remotes: {
        host: "http://localhost:3000/remoteEntry.js"
      },
      shared: ["vue"]
    })
  ]
};

// 在子项目中使用
import SCDrawer from 'host/SCDrawer';

结论

将 Vue 组件直接放入 window 对象并跨应用共享通常不是最佳实践,特别是在涉及复杂组件和状态管理时。使用组件库、Webpack externals 或模块联邦等更现代和可靠的方法,可以更好地管理微前端架构中的组件共享。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏