微前端架构解决什么问题
微前端将大型单体前端应用拆分为多个独立开发、独立部署的子应用,每个子应用可以使用不同的框架和技术栈。这种架构解决的核心问题是大型团队协作中的代码冲突、构建缓慢和部署耦合。当前端代码量达到百万行级别时,单仓库的构建时间可能超过30分钟,任何子功能的修改都需要全量构建部署,微前端将构建和部署拆解为独立单元。
微前端方案主要分为两类:基于运行时隔离的qiankun和基于构建时集成的Module Federation。两者的设计理念不同,适用场景也有差异。
qiankun运行时隔离方案
qiankun基于single-spa封装,通过HTML Entry方式加载子应用。主应用通过fetch获取子应用的HTML文件,解析出JS和CSS资源,在沙箱环境中执行子应用代码。
// 主应用 - 注册子应用
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
{
name: 'user-app',
entry: '//localhost:8081',
container: '#subapp-container',
activeRule: '/user',
},
{
name: 'order-app',
entry: '//localhost:8082',
container: '#subapp-container',
activeRule: '/order',
},
]);
start({
prefetch: true, // 预加载子应用
sandbox: {
strictStyleIsolation: true, // Shadow DOM样式隔离
experimentalStyleIsolation: true,
},
});
// 子应用 - 导出生命周期函数
export async function mount(props) {
ReactDOM.render(
,
props.container
? props.container.querySelector('#root')
: document.getElementById('root')
);
}
export async function unmount(props) {
ReactDOM.unmountComponentAtNode(
props.container
? props.container.querySelector('#root')
: document.getElementById('root')
);
}
qiankun的JS沙箱通过Proxy代理window对象实现隔离,子应用对window的修改不会影响主应用和其他子应用。strictStyleIsolation使用Shadow DOM隔离样式,experimentalStyleIsolation通过CSS Scope规则给子应用样式添加前缀。两者各有取舍:Shadow DOM隔离更彻底但可能导致弹窗组件样式失效,Scope方式兼容性更好但隔离不完整。
Module Federation构建时集成方案
Module Federation是Webpack 5原生支持的模块联邦功能,允许不同构建产物之间在运行时共享模块。与qiankun不同,Module Federation不依赖HTML Entry,而是直接共享JS模块。
// 子应用 webpack.config.js
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'userApp',
filename: 'remoteEntry.js',
exposes: {
'./UserModule': './src/components/UserModule',
'./UserService': './src/services/UserService',
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true },
'react-router-dom': { singleton: true },
},
}),
],
};
// 主应用 webpack.config.js
new ModuleFederationPlugin({
name: 'shell',
remotes: {
userApp: 'userApp@//localhost:8081/remoteEntry.js',
orderApp: 'orderApp@//localhost:8082/remoteEntry.js',
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true },
},
})
// 主应用 - 动态加载子应用模块
const UserModule = React.lazy(() =>
import('userApp/UserModule')
);
const OrderModule = React.lazy(() =>
import('orderApp/OrderModule')
);
function App() {
return (
}>
} />
} />
);
}
shared配置中的singleton: true确保React、ReactDOM等公共依赖只加载一次,避免多个子应用各自加载一份导致内存浪费和Hook失效问题。requiredVersion指定版本要求,当子应用的依赖版本不满足时Webpack会发出警告。
两种方案的对比与选型
qiankun和Module Federation在架构层面有本质区别:
| 维度 | qiankun | Module Federation |
|-------------|--------------------------|------------------------|
| 隔离机制 | JS沙箱+Shadow DOM | 共享模块+单例依赖 |
| 加载方式 | HTML Entry fetch | JS模块动态import |
| 框架兼容 | 支持不同框架混用 | 需要Webpack 5+ |
| 样式隔离 | Shadow DOM/Scope | 需要CSS Modules手动处理 |
| 通信方式 | props传递/全局状态 | 直接import共享模块 |
| 公共依赖 | 各自加载 | shared配置共享单例 |
| 改造成本 | 子应用需导出生命周期 | 需升级Webpack 5并配置 |
| 适用场景 | 跨技术栈/遗留系统集成 | 同技术栈/新项目微前端 |
实际选型需要考虑团队现状。如果团队中存在Vue、React甚至Angular混用的场景,qiankun的框架无关性是决定性优势。如果所有子应用统一使用React+Webpack技术栈,Module Federation的模块级共享更加高效,公共依赖只加载一份,页面体积更小。
微前端通信机制设计
微前端架构中子应用之间的通信是核心难点。常见的方案包括:
// 方案1:基于CustomEvent的发布订阅
// 主应用
window.dispatchEvent(new CustomEvent('user-updated', {
detail: { userId: 123, name: '张三' }
}));
// 子应用
window.addEventListener('user-updated', (e) => {
console.log('收到用户更新:', e.detail);
});
// 方案2:基于全局状态管理(qiankun props传递)
// 主应用
registerMicroApps([{
name: 'user-app',
entry: '//localhost:8081',
container: '#subapp-container',
activeRule: '/user',
props: {
getToken: () => localStorage.getItem('token'),
onUserChange: (user) => sharedStore.setUser(user),
},
}]);
// 方案3:Module Federation共享Service
// shared/service/store.ts(共享模块)
import { createStore } from 'zustand';
export const useSharedStore = createStore((set) => ({
user: null,
setUser: (user) => set({ user }),
cart: [],
addToCart: (item) => set((s) => ({ cart: [...s.cart, item] })),
}));
// 各子应用直接import使用
import { useSharedStore } from 'shell/sharedStore';
const user = useSharedStore((s) => s.user);
CustomEvent方案最简单但缺乏类型安全。props传递方案在qiankun中官方支持但通信能力有限。Module Federation的共享模块方案类型安全且最灵活,但要求所有子应用使用相同的状态管理库。
部署策略与路由管理
微前端的部署需要处理路由分发和资源加载。Nginx配置根据路径将请求代理到不同的子应用服务器:
server {
listen 80;
server_name app.example.com;
# 主应用
location / {
proxy_pass http://127.0.0.1:8000;
}
# 子应用静态资源
location /user/ {
proxy_pass http://127.0.0.1:8081;
try_files $uri $uri/ /user/index.html;
}
location /order/ {
proxy_pass http://127.0.0.1:8082;
try_files $uri $uri/ /order/index.html;
}
# API网关
location /api/ {
proxy_pass http://127.0.0.1:3000;
}
}
路由管理需要处理子应用切换时的状态保持和页面刷新。qiankun通过activeRule匹配URL前缀激活对应子应用,Module Federation通过React Router的嵌套路由实现。页面刷新时确保子应用资源能正确加载,Nginx的try_files配置将未匹配的路径回退到子应用的index.html。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/wei-qian-duan-jia-gou-shi-zhan-qiankun-yu-modulefederation/