7、模块联邦和微前端架构实战

137 阅读3分钟

🪜 写在前面

当前端团队规模扩大,每个业务线都拥有独立项目后,会面临这些问题:

  • 如何让多个前端项目解耦、独立部署又能组合展示?
  • 如何让子团队独立开发、独立上线,又共享公共组件?
  • 如何解决“更新公共组件 A 要打所有项目包”的痛点?

这就是微前端与**模块联邦(Module Federation)**登场的地方。

这一篇我们将:

  • 掌握微前端 2 种主流架构(qiankun + Module Federation)
  • 基于 Vite + Vue3 实战实现“模块联邦共享组件”
  • 对比常见痛点与适配策略

📦 一、微前端 vs 模块联邦(区别和联系)

特性qiankun(框架型)Module Federation(构建型)
实现方式运行时沙箱、iframe-like构建时拆包、共享模块
技术适配所有框架(Vue/React/Angular)Webpack5/Vite(需插件)
加载方式HTML + JS 异步插入remoteEntry 动态加载 chunk
场景优势主子系统完全解耦组件共享、统一系统更高效
弊端沙箱隔离问题、通信复杂构建依赖要求高、升级麻烦

🔧 二、实战准备:模块联邦架构(基于 Vite + Vue3)

🧱 架构图:

        ┌────────────┐
        │  host-app  │ ──┬──加载子模块1remote-app1)
        └────────────┘   └──加载子模块2remote-app2)
          │
          │
     exposes: Button  ← 远程共享组件 exposed 出来

🧰 三、项目结构预览

micro-frontends/
├── host-app/          # 主应用
├── remote-app1/       # 子应用 1(暴露组件)
└── remote-app2/       # 子应用 2(暴露页面)

🚀 四、子应用 remote-app1(暴露组件)

✅ 1. 安装依赖(vite-module-federation)

npm i -D @originjs/vite-plugin-federation

✅ 2. vite.config.ts 设置模块暴露

// remote-app1/vite.config.ts
import federation from '@originjs/vite-plugin-federation'

export default {
  plugins: [
    federation({
      name: 'remote_app1',
      filename: 'remoteEntry.js',
      exposes: {
        './FancyButton': './src/components/FancyButton.vue',
      },
      shared: ['vue'],
    }),
  ],
  build: {
    target: 'esnext',
    minify: false,
    cssCodeSplit: false,
  },
}

👀 五、主应用 host-app(远程加载子模块)

✅ 1. vite.config.ts 中 remote 配置

// host-app/vite.config.ts
import federation from '@originjs/vite-plugin-federation'

export default {
  plugins: [
    federation({
      name: 'host',
      remotes: {
        remote_app1: 'http://localhost:5001/assets/remoteEntry.js',
      },
      shared: ['vue'],
    }),
  ],
}

✅ 2. 在主应用中动态引入远程组件

// host-app/src/App.vue
<script setup>
import { defineAsyncComponent } from 'vue'

const RemoteButton = defineAsyncComponent(() =>
  import('remote_app1/FancyButton')
)
</script>

<template>
  <h2>主应用加载远程按钮:</h2>
  <RemoteButton />
</template>

✅ 效果: 主应用无需打包 remote 的 FancyButton,即可直接使用远程子项目的组件!


🧩 六、典型痛点与应对策略

问题应对方案
子项目变动导致主项目构建失败使用 external 配置,主项目懒加载
多个项目依赖 vue 不一致设置 shared: { vue: { singleton: true, requiredVersion: '^3.3' } }
本地调试 remote 加载失败使用 nginx 本地代理 + Vite dev config
远程组件样式不一致建议 remote 封装 UI 样式隔离(Scoped or BEM)
类型提示丢失搭配 @types/remote-module.d.ts 模拟暴露模块

🧰 七、实战建议与落地模式

✅ 推荐使用场景:

  1. 多业务线组件库共享(如:Button / Table / Card)
  2. 配置平台 + 运营活动平台共享模块
  3. 低代码平台组件运行时按需加载
  4. 设计平台实时预览远程组件能力
  5. 高并发系统的按需拆包加载降初包体积

🛠️ 八、构建部署建议(CI/CD)

  • 子项目构建后上传 remoteEntry 到 CDN
  • 主项目运行时读取 CDN 地址
  • 可设置版本号,如:
remotes: {
  remote_app1: `https://cdn.xxx.com/remote-app1/1.0.0/remoteEntry.js`,
}

✅ 九、微前端实战对比(qiankun)

场景推荐方式
系统完全解耦、独立部署✅ qiankun
只想共享组件 / hook / 模块✅ Module Federation
公司已有主子仓库、统一权限✅ qiankun
想要按需加载优化包体积✅ Module Federation

🧠 总结一句话

模块联邦是“架构级代码共享”方案,是构建可插拔式系统的关键能力。


下一篇我们将落地「工程流程整合能力」: 👉 《前端 CI/CD 流程全解析与实战部署》