当前位置: 首页 > 知识库问答 >
问题:

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

易炳
2024-07-30

我现在的做法是在主项目中将组件放到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版本是一样的
请问大佬们 有没有什么解决的方法 或者有其他主子应用共享组件的方法也行

共有1个答案

苏胤
2024-07-30

在 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 或模块联邦等更现代和可靠的方法,可以更好地管理微前端架构中的组件共享。

 类似资料:
  • 我正在使用sbt 0.13.12,这是我的项目 在构建中。sbt取决于公共。如果我按sbt project sub1 run运行就可以了。但是,当我将子项目打包为jar文件时,我运行sub1。jar文件中,错误显示sub1无法找到一类公共的。 我的目的是包装sub1。jar和sub2。在每个jar文件中编译带有通用代码的jar。 --更新-- 我尝试作为建议回答。运行时遇到这个问题: 而且,是的!

  • qiankun+vue3主项目umi4子项目,子项目成功加载但是在render的下一帧就404了,或许是路由配置有问题。 我像这样注册了我的umi子项目进行测试: 这便是umi子项目sub-app-2的.umirc.ts中的配置: 由于我选用了一个开源的叫做like-admin的一个Vue3项目作为基座,它的菜单和路由结构是类似这样: 也就是类似 /目录/路由 的结构;然后在进入子项目2也就是我们

  • 问题内容: 我正在一个较大的项目中,其中包含许多子项目,这些子项目都是用gradle构建的。通常所有项目都是java项目,因此在主build.gradle脚本中 为所有项目指定。 但是,我需要为项目的某个子树删除插件,或者从插件中明确排除项目。 这里是项目布局的粗略概述 Android / *不需要Java插件。实现此目标的最佳解决方案是什么?注意:我无法更改项目结构。 问题答案: 这应该可以解决

  • sbt子项目是否可以有自己的目录?或者只有根项目可以用。Scala帮助器文件为构建项目的目录?。下面是我目前的建筑结构。无法访问中定义的对象。 更新:sub-project-1/build.sbt中的以下sbt定义 由于以下错误而失败 Common在/my-project/projects/Common.scala中定义,没有问题。但是Localhost是在/my-project/sub-proj

  • 我正在获取库项目中Examid字符串的空值。

  • 我的共享主机帐户上有第二个域 我的laravel项目位于根目录中 laravel公用文件夹位于public_html下。public\u html/public 注意:我不希望公共文件直接位于public_html下,因为我还有其他文件会被覆盖。 我已经将这些更改为索引中的行。php文件。 需要目录。“//肌醇结构域。com/供应商/自动加载。php′; require_onceDIR/.../.