微前端
一、是什么
微前端是将前端应用拆分为多个独立部署、独立运行、技术栈无关的子应用,由一个基座应用(容器)在运行时动态组合,形成完整前端体验。
类比后端:微服务 → 前端:微前端
二、为什么
| 场景 | 说明 |
|---|---|
| 大型团队协作 | 不同子应用由不同团队独立开发、测试、部署 |
| 多业务线系统 | CRM、ERP、BI 等系统集成在一个统一门户中 |
| 技术栈不统一 | 老系统升级、不同团队技术偏好不同 |
| 增量迁移 | 逐步将巨型 SPA 拆解或重构 |
三、实现方案
1. iframe(最简单)
- ✅ 完全隔离:JS/CSS 互不影响
- ✅ 原生支持,无侵入
- ❌ 路由不同步(刷新/前进后退问题)
- ❌ 通信困难(postMessage 繁琐)
- ❌ 弹窗/全局遮罩无法跨 iframe
- ❌ 性能开销大(每个 iframe 独立上下文)
适用:简单嵌入类场景(如运营活动页、第三方报表)
2. single-spa
import { registerApplication, start } from 'single-spa';
registerApplication({
name: 'app1',
app: () => import('app1/main.js'),
activeWhen: ['/app1'],
});
start();
-
✅ 路由级拆分
-
✅ 多框架支持(React/Vue/Angular)
-
❌ 需要自行解决:样式隔离、JS沙箱、公共依赖加载
3. Module Federation
// webpack.config.js
new ModuleFederationPlugin({
name: 'host',
remotes: {
app2: 'app2@http://localhost:3002/remoteEntry.js',
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
},
});
-
✅ 运行时动态加载远程模块
-
✅ 依赖共享(避免重复打包 React/Vue)
-
✅ 支持模块级拆分(不只是应用级)
-
❌ 配置复杂
-
❌ 强依赖 Webpack(但已逐步被 Rspack 等兼容)
目前生产最常用的方案之一
4. qiankun (基于 single-spa)
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
{
name: 'app1',
entry: '//localhost:3001',
container: '#container',
activeRule: '/app1',
},
]);
start();
-
✅ 开箱即用:JS沙箱(Proxy)、样式隔离(shadow DOM 或 scoped)
-
✅ HTML Entry(自动加载 JS/CSS)
-
✅ 阿里生产验证(蚂蚁、菜鸟等)
-
❌ 对 Vite 支持较弱(需插件)
-
❌ 依赖 single-spa 生态
5. 新兴方案(2024+)
| 方案 | 特点 |
|---|---|
| wujie(腾讯) | 基于 WebComponent + iframe 沙箱,更轻量 |
| micro-app(京东) | 类 qiankun 但更轻,支持 Vite |
| 无界 | 支持 iframe 沙箱 + 路由同步 |
四、核心问题与解决方式
| 问题 | 难点 | 主流解法 |
|---|---|---|
| 子应用通信 | 跨应用状态共享、事件传递 | ① 基座事件总线(mitt / eventemitter)<br>② 全局状态管理(Redux / Zustand 挂载到 window)<br>③ 路由参数传递(简单场景)<br>④ 自定义浏览器事件(CustomEvent) |
| 样式隔离 | CSS 规则相互污染、覆盖 | ① CSS Modules / Scoped CSS(构建时隔离)<br>② Shadow DOM(qiankun 可选,强隔离)<br>③ BEM 命名约定 + 动态添加前缀<br>④ CSS-in-JS(运行时隔离) |
| JS 沙箱 | 全局变量冲突、setTimeout/监听未清理、原型链污染 | ① Proxy 劫持 window(qiankun 沙箱)<br>② iframe 天然隔离(最强但最重)<br>③ 快照沙箱(降级方案,性能较差)<br>④ with + new Function 模拟作用域 |
| 路由同步 | 子应用独立路由 + 主应用路由协同,刷新/前进后退保持状态 | 主应用监听路由变化,通过 activeRule 激活子应用;子应用使用 memory 模式或继承基座路由(如 createWebHistory(base)) |
| 公共依赖加载 | 多个子应用重复加载 React/Vue 等框架,首屏臃肿 | ① Module Federation shared 配置共享<br>② externals + CDN 统一加载<br>③ 基座注入公共依赖(window.React) |
| 性能(首屏) | 主应用 + 多个子应用资源同时加载 | ① 按需激活(路由懒加载)<br>② 子应用预加载(prefetch,用户 hover 菜单时)<br>③ 公共依赖强缓存<br>④ 子应用资源走 CDN |
| 子应用生命周期 | 子应用独立运行时 vs 被基座加载时的行为差异 | 子应用导出 bootstrap / mount / unmount 生命周期;通过 window.__POWERED_BY_QIANKUN__ 等全局标志判断环境 |
| 构建产物兼容 | 子应用打包出的 JS/CSS 可能污染全局或路径错误 | ① 子应用配置 webpack publicPath 为动态(window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__)<br>② 启用 asset 模块时设置 output.publicPath: 'auto' |
通信详解示例(事件总线)
// 基座
import mitt from 'mitt';
window.microAppEventBus = mitt();
// 子应用 A 发送
window.microAppEventBus.emit('user-logout', { userId: 123 });
// 子应用 B 接收
window.microAppEventBus.on('user-logout', (data) => {
console.log('清除本地缓存', data);
});
JS 沙箱简化原理(qiankun 实现思路)
class ProxySandbox {
constructor() {
const fakeWindow = Object.create(null);
this.proxy = new Proxy(fakeWindow, {
get: (target, prop) => target[prop] || window[prop],
set: (target, prop, value) => {
target[prop] = value;
return true;
},
});
}
}
五、最佳实践
1. 拆分粒度控制
- ✅ 按业务域拆分:用户中心、订单中心、商品管理、支付中心
- ✅ 按稳定度拆分:核心交易流程(稳定) vs 营销活动(频繁变更)
- ✅ 按团队边界拆分:一个团队维护 1-2 个子应用
- ❌ 不要按页面/组件过度拆分:增加通信和加载成本
- ❌ 子应用数量建议 ≤ 20,过多则运维复杂、版本管理混乱
粒度判断标准:
- 能否独立部署且不影响其他子应用?
- 是否有独立的业务价值?
- 团队是否能独立决策其技术栈?
2. 统一基建(基座职责)
基座是微前端的"操作系统",统一提供以下能力,避免每个子应用重复造轮子
// 基座向子应用注入能力
if (window.__POWERED_BY_QIANKUN__) {
window.__INJECTED_UTILS__ = {
// 网络请求(统一 token、拦截器、错误处理)
request: (url, options) =>
fetch(url, { ...options, credentials: 'include' }),
// 事件总线
eventBus: window.microAppEventBus,
// 用户信息
getUser: () => window.__GLOBAL_USER__,
// 权限校验
hasPermission: (code) => window.__PERMISSIONS__.includes(code),
// 埋点上报
track: (eventName, data) => {
/* 统一上报 */
},
// 全局通知
notification: { success, error, warning },
};
}
3. 与 Monorepo 的强绑定(工程化核心)
没有 Monorepo 的微前端,依赖管理和公共库升级会非常痛苦
目录结构示例:
monorepo/
packages/
base/ # 基座应用
user-center/ # 用户中心子应用
order/ # 订单子应用
product/ # 商品子应用
shared/ # 公共组件/工具/类型/常量
src/
components/ # Button、Modal 等
utils/ # formatDate、deepClone
hooks/ # useRequest、useAuth
types/ # 全局 TS 类型
config-eslint/ # 统一 ESLint 配置
config-typescript/ # 统一 TS 配置
package.json
pnpm-workspace.yaml
turbo.json