出处:掘金

原作者:金泽宸


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

写在前面

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

  • 如何让多个前端项目解耦、独立部署又能组合展示?
  • 如何让子团队独立开发、独立上线,又共享公共组件?
  • 如何解决“更新公共组件 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  │ ──┬──加载子模块1(remote-app1)
    └────────────┘   └──加载子模块2(remote-app2)


     exposes: Button  ← 远程共享组件 exposed 出来

项目结构预览:

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

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

安装依赖(vite-module-federation):

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

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(远程加载子模块)

vite.config.tsremote 配置:

// 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'],
    }),
  ],
}

在主应用中动态引入远程组件:

// host-app/src/App.vue
<script setup>
import { defineAsyncComponent } from 'vue'
 
const RemoteButton = defineAsyncComponent(() =>
  import('remote_app1/FancyButton')
)
</script>
 
<template>
  <h2>主应用加载远程按钮:</h2>
  <RemoteButton />
</template>

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

典型痛点与应对策略

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

实战建议与落地模式

推荐使用场景:

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

构建部署建议(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