出处:掘金

原作者:金泽宸


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

写在前面

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

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

这一篇我们将:

微前端 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 模拟暴露模块

实战建议与落地模式

推荐使用场景:

构建部署建议(CI/CD)

remotes: {
  remote_app1: `https://cdn.xxx.com/remote-app1/1.0.0/remoteEntry.js`,
}

微前端实战对比(qiankun)

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