出处:掘金
原作者:金泽宸
模块联邦是“架构级代码共享”方案,是构建可插拔式系统的关键能力
当前端团队规模扩大,每个业务线都拥有独立项目后,会面临这些问题:
这就是微前端与==模块联邦(Module Federation)==登场的地方
这一篇我们将:
| 特性 | 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(暴露页面)
安装依赖(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,
},
}
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'],
}),
],
}
在主应用中动态引入远程组件:
// 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 模拟暴露模块 |
推荐使用场景:
remotes: {
remote_app1: `https://cdn.xxx.com/remote-app1/1.0.0/remoteEntry.js`,
}
| 场景 | 推荐方式 |
|---|---|
| 系统完全解耦、独立部署 | qiankun |
| 只想共享组件 / hook / 模块 | Module Federation |
| 公司已有主子仓库、统一权限 | qiankun |
| 想要按需加载优化包体积 | Module Federation |