前端乾坤与模块联邦的用法及区别
概述
乾坤(Qiankun)和模块联邦(Module Federation)是前端微服务架构中常用的两种技术方案,用于实现模块化开发、动态加载和跨应用共享代码。两者在微前端场景下有各自的特点和适用场景。本文将详细介绍它们的用法、核心概念以及主要区别。
一、乾坤(Qiankun)
1. 简介
乾坤是基于 single-spa 的微前端框架,由蚂蚁金服开源,旨在提供开箱即用的微前端解决方案。它通过主应用和子应用的分离,动态加载子应用,支持多种前端框架(如 React、Vue、Angular 等)。
2. 核心概念
- 主应用(Main App):负责加载和管理子应用,控制路由和生命周期。
- 子应用(Sub App):独立的微前端应用,可以使用不同技术栈,动态加载到主应用中。
- 生命周期:乾坤定义了子应用的生命周期钩子,包括
bootstrap、mount和unmount。 - 沙箱机制:通过 JS 沙箱(ProxySandbox 或 SnapshotSandbox)隔离子应用的全局变量和样式,防止冲突。
- 通信机制:通过全局状态管理(如
initGlobalState)或事件机制实现主子应用通信。
3. 用法
主应用配置
主应用需引入乾坤并注册子应用:
// main.js
import { registerMicroApps, start } from 'qiankun';
const apps = [
{
name: 'reactApp',
entry: '//localhost:3001', // 子应用入口
container: '#subapp-container', // 渲染容器
activeRule: '/react', // 路由匹配规则
},
{
name: 'vueApp',
entry: '//localhost:3002',
container: '#subapp-container',
activeRule: '/vue',
},
];
registerMicroApps(apps);
start({
prefetch: true, // 预加载子应用资源
sandbox: { experimentalStyleIsolation: true }, // 开启样式隔离
});
子应用配置
子应用需暴露生命周期钩子:
// 子应用入口文件
export async function bootstrap() {
console.log('子应用初始化');
}
export async function mount(props) {
console.log('子应用挂载', props);
// 渲染逻辑
}
export async function unmount() {
console.log('子应用卸载');
// 清理逻辑
}
通信
主应用通过 initGlobalState 初始化全局状态:
import { initGlobalState } from 'qiankun';
const state = { user: 'admin' };
const actions = initGlobalState(state);
actions.onGlobalStateChange((newState, prev) => {
console.log('全局状态变更', newState, prev);
});
子应用通过 props 接收状态:
export async function mount(props) {
props.onGlobalStateChange((state, prev) => {
console.log('子应用接收状态', state);
});
}
4. 优点
- 开箱即用:提供完整的微前端解决方案,集成路由、沙箱和通信机制。
- 技术栈无关:支持多种框架,子应用无需大幅修改。
- 沙箱隔离:内置 JS 和 CSS 隔离机制,减少冲突。
- 生态丰富:与 single-spa 生态兼容,社区支持完善。
5. 缺点
- 侵入性:子应用需适配乾坤的生命周期,略有改造成本。
- 性能开销:沙箱机制可能增加性能消耗,尤其在多子应用场景。
- 复杂场景适配:对复杂路由或深度集成场景需额外配置。
二、模块联邦(Module Federation)
1. 简介
模块联邦是 Webpack 5 引入的功能,允许在构建时将多个独立构建的应用模块化共享代码,实现动态加载和运行时共享。它更偏向于模块级别的复用,而不是完整的应用加载。
2. 核心概念
- 主机(Host):加载远程模块的应用。
- 远程(Remote):暴露模块供其他应用使用的应用。
- 模块暴露:通过
exposes配置暴露模块,供主机消费。 - 模块消费:通过
remotes配置引用远程模块。 - 共享模块:通过
shared配置共享依赖(如 React、Vue),减少重复加载。
3. 用法
主机应用配置
在 webpack.config.js 中配置:
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'host',
remotes: {
remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
}),
],
};
远程应用配置
在远程应用的 webpack.config.js 中暴露模块:
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'remoteApp',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/Button',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
}),
],
};
使用远程模块
在主机应用中动态加载远程模块:
import React, { lazy, Suspense } from 'react';
const RemoteButton = lazy(() => import('remoteApp/Button'));
function App() {
return (
<Suspense fallback="Loading...">
<RemoteButton />
</Suspense>
);
}
4. 优点
- 轻量灵活:仅处理模块级共享,无需生命周期管理,侵入性低。
- 运行时加载:支持动态加载模块,适合按需加载场景。
- 依赖共享:通过
shared机制减少重复依赖加载,优化性能。 - 生态支持:Webpack 生态强大,适配现代前端工具链。
5. 缺点
- 配置复杂:需要手动配置 Webpack,学习成本较高。
- 隔离性弱:无内置沙箱机制,需自行处理样式和全局变量冲突。
- 功能局限:更适合模块共享,不适合完整应用的微前端架构。
三、乾坤与模块联邦的区别
| 特性 | 乾坤(Qiankun) | 模块联邦(Module Federation) |
|---|---|---|
| 定位 | 完整的微前端框架 | Webpack 的模块共享机制 |
| 核心功能 | 子应用加载、路由管理、沙箱隔离、通信 | 模块动态加载、依赖共享 |
| 技术栈支持 | 支持多种框架(React、Vue 等) | 依赖 Webpack,框架无关 |
| 隔离机制 | 内置 JS 和 CSS 沙箱 | 无内置沙箱,需手动处理隔离 |
| 通信机制 | 全局状态管理、事件机制 | 通过模块 props 或自定义通信 |
| 使用场景 | 适合复杂微前端项目,需加载完整子应用 | 适合模块级共享,按需加载组件或功能 |
| 侵入性 | 子应用需适配生命周期钩子 | 侵入性低,仅需配置 Webpack |
| 性能 | 沙箱和生命周期管理有一定开销 | 轻量,依赖共享优化性能 |
| 学习成本 | 简单,文档完善 | 配置复杂,需熟悉 Webpack |
四、适用场景分析
1. 选择乾坤的场景
- 需要管理多个完整的前端应用(如不同团队开发的独立项目)。
- 对隔离性要求高(如需要严格的 JS 和 CSS 隔离)。
- 希望快速集成多种技术栈的应用,追求开箱即用。
- 需要统一的路由管理和全局状态管理。
2. 选择模块联邦的场景
- 需要在多个应用间共享特定模块或组件(如共享一个通用按钮组件)。
- 追求轻量级模块加载,减少重复依赖加载。
- 项目基于 Webpack 构建,团队熟悉 Webpack 配置。
- 不需要复杂的子应用生命周期管理。
五、总结
乾坤和模块联邦都是前端微服务化的重要工具,但定位和实现方式不同:
- 乾坤 更适合需要管理多个完整应用的微前端场景,提供全面的隔离和通信机制,适合复杂项目。
- 模块联邦 更适合模块级别的共享和动态加载,配置灵活但隔离性较弱,适合轻量级模块复用场景。
根据项目需求选择合适的方案:
- 如果是大型微前端项目,推荐使用乾坤以获得完整的框架支持。
- 如果是模块共享或轻量级微前端场景,模块联邦是更好的选择。

沪公网安备31011502403869号