华为云 DevUI 微前端实战:基于 Module Federation 的多团队协作架构落地
作者 :晚霞的不甘
日期 :2025年12月7日
适用对象 :中大型企业前端负责人、微前端实践者、DevOps 工程师
前置知识:熟悉 Angular、Webpack 5、微前端概念,建议已阅读《DevUI 高级实战》
一、引言:为什么企业需要微前端?
随着业务复杂度激增,传统单体前端应用面临严峻挑战:
- 🧩 代码臃肿:一个 Git 仓库包含数十个业务模块,PR 审查困难
- ⏳ 构建缓慢:全量构建耗时 10+ 分钟,影响交付效率
- 🤝 团队耦合:多个团队共用一套技术栈,升级需协调所有人
- 🚫 技术锁定:无法引入新框架(如 Vue 3、React 18)验证新业务
微前端(Micro Frontends) 正是解决这些问题的架构范式。而华为云 DevUI 凭借其设计一致性、组件隔离性与工程友好性,成为构建微前端系统的理想 UI 基座。
本文将手把手教你:
- ✅ 搭建基于 Webpack 5 Module Federation 的微前端主子应用体系
- ✅ 实现 DevUI 主题/组件/状态 在微应用间的共享与隔离
- ✅ 设计 统一登录、权限、埋点 的跨应用通信机制
- ✅ 落地 CI/CD 流水线 支持独立部署与灰度发布
二、整体架构设计
1. 系统拓扑图
┌───────────────────┐
│ 用户浏览器 │
└─────────┬─────────┘
│
┌───────────────────▼───────────────────┐
│ Shell 主应用 (admin-shell) │ ← 统一入口
│ - 全局布局 │
│ - 路由分发 │
│ - 共享依赖 (DevUI, RxJS, etc.) │
└───────────────────┬───────────────────┘
│
┌───────────────────────┼───────────────────────┐
│ │ │
┌──────▼───────┐ ┌──────────▼──────────┐ ┌─────────▼─────────┐
│ 任务中心 │ │ 用户管理 │ │ 数据分析 │
│ (task-center)│ │ (user-management) │ │ (data-insights) │
│ - Angular 16 │ │ - Angular 17 │ │ - Vue 3 + DevUI │
│ - 独立部署 │ │ - 独立部署 │ │ - 独立部署 │
└──────────────┘ └─────────────────────┘ └───────────────────┘
💡 关键原则:
- Shell 应用只负责集成,不包含业务逻辑
- 每个微应用可独立开发、测试、部署、回滚
- 共享核心依赖,避免重复打包
三、环境搭建:Nx + Webpack Module Federation
1. 初始化工作区
bash
npx create-nx-workspace@latest devui-mfe --preset=empty
cd devui-mfe
npm install @nrwl/angular @angular/cli --save-dev
2. 创建主应用(Shell)
bash
nx g @nrwl/angular:app admin-shell --routing --style=scss
3. 安装 Module Federation 插件
bash
npm install @angular-architects/module-federation --save-dev
nx g @angular-architects/module-federation:ng-add --project admin-shell
4. 创建微应用(以 task-center 为例)
bash
nx g @nrwl/angular:app task-center --routing --style=scss
nx g @angular-architects/module-federation:ng-add --project task-center --port 4201
📌 端口分配建议:
- Shell: 4200
- Task Center: 4201
- User Mgmt: 4202
- Data Insights: 4203
四、核心配置详解
1. Shell 应用配置(暴露共享依赖)
js
// apps/admin-shell/webpack.config.js
const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');
module.exports = withModuleFederationPlugin({
name: 'admin_shell',
exposes: {
// 暴露全局服务(供微应用使用)
'./GlobalStateService': './libs/core/src/lib/services/global-state.service.ts',
'./PermissionService': './libs/core/src/lib/services/permission.service.ts'
},
shared: {
...shareAll({
singleton: true, // 单例模式(关键!)
strictVersion: true, // 严格版本校验
requiredVersion: 'auto',
includeSecondaries: false
})
}
});
🔑 关键点:
singleton: true确保 DevUI、Angular Core 等只加载一次- 暴露
GlobalStateService实现跨应用状态同步
2. 微应用配置(消费共享依赖)
js
// apps/task-center/webpack.config.js
const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');
module.exports = withModuleFederationPlugin({
name: 'task_center',
filename: 'remoteEntry.js',
exposes: {
'./Routes': './apps/task-center/src/app/remote-routes.ts',
'./TaskModule': './apps/task-center/src/app/task/task.module.ts'
},
shared: {
...shareAll({
singleton: true,
strictVersion: true,
requiredVersion: 'auto'
})
}
});
3. 共享依赖清单(package.json 片段)
json
{
"dependencies": {
"@devui-design/devui": "^16.0.0",
"@angular/core": "~16.2.0",
"rxjs": "~7.8.0"
},
"moduleFederation": {
"sharedDependencies": [
"@angular/core",
"@angular/common",
"@angular/router",
"rxjs",
"@devui-design/devui"
]
}
}
⚠️ 避坑指南:
- 所有应用必须使用相同主版本的 DevUI 和 Angular
- 避免在微应用中直接 import Shell 的业务组件
五、DevUI 在微前端中的最佳实践
1. 主题一致性保障
方案:通过 CSS Variables 全局注入
scss
/* libs/styles/src/lib/themes/default.scss */
:root {
--devui-brand-primary: #626ae9;
--devui-border-radius: 6px;
--devui-font-size-base: 14px;
}
/* 在 Shell 的 index.html 中引入 */
<link rel="stylesheet" href="/assets/themes/default.css">
✅ 优势:所有微应用自动继承主题,无需重复配置
2. 图标系统统一
方案:在 Shell 中注册全局图标
ts
// apps/admin-shell/src/main.ts
import { DevuiIconService } from 'ng-devui/icon';
import { customIcons } from '@enterprise/icons';
platformBrowserDynamic().bootstrapModule(AppModule).then(() => {
const iconService = new DevuiIconService();
Object.entries(customIcons).forEach(([name, svg]) => {
iconService.registerIcon(name, svg);
});
});
🖼️ 效果 :微应用可直接使用
<devui-icon icon="custom-task"></devui-icon>
3. 组件隔离与复用
| 场景 | 推荐方案 |
|---|---|
| 公共表单控件 | 发布为 Nx Lib(如 @enterprise/shared/ui-forms) |
| 业务专属组件 | 保留在微应用内部 |
| 弹窗/通知等 | 使用 Shell 提供的全局服务调用 |
示例:调用 Shell 的 Toast 服务
ts
// 微应用中
import { loadRemoteModule } from '@angular-architects/module-federation';
async showSuccess(message: string) {
const { GlobalToastService } = await loadRemoteModule({
remoteName: 'admin_shell',
exposedModule: './GlobalToastService'
});
GlobalToastService.success(message);
}
六、跨应用通信机制
1. 全局状态同步(推荐)
ts
// libs/core/src/lib/services/global-state.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class GlobalStateService {
private userSubject = new BehaviorSubject<User | null>(null);
user$ = this.userSubject.asObservable();
setUser(user: User) {
this.userSubject.next(user);
// 同步到 localStorage(供新打开的微应用读取)
localStorage.setItem('global_user', JSON.stringify(user));
}
}
微应用启动时同步状态:
ts
// apps/task-center/src/main.ts
import { GlobalStateService } from 'admin_shell/GlobalStateService';
const globalState = new GlobalStateService();
const savedUser = localStorage.getItem('global_user');
if (savedUser) {
globalState.setUser(JSON.parse(savedUser));
}
2. 事件总线(轻量级场景)
ts
// 全局事件类型
export type GlobalEvent =
| { type: 'user:logout' }
| { type: 'theme:change'; payload: string };
// 发送事件
window.dispatchEvent(new CustomEvent('global-event', { detail: { type: 'user:logout' } }));
// 监听事件
window.addEventListener('global-event', (e: any) => {
if (e.detail.type === 'user:logout') {
// 执行登出逻辑
}
});
⚠️ 注意:避免过度使用事件总线,优先考虑状态服务
七、CI/CD 流水线设计
1. 独立构建与部署
yaml
# .github/workflows/deploy-task-center.yml
name: Deploy Task Center
on:
push:
branches: [ main ]
paths: [ 'apps/task-center/**', 'libs/**' ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm ci
- run: npx nx build task-center --configuration=production
- name: Deploy to OBS
uses: huaweicloud/obs-deploy-action@v1
with:
access-key-id: ${{ secrets.OBS_ACCESS_KEY }}
secret-access-key: ${{ secrets.OBS_SECRET_KEY }}
bucket: task-center-prod
source-dir: dist/apps/task-center
2. 灰度发布策略
- 版本控制 :微应用发布时生成带 hash 的
remoteEntry.js - Shell 配置中心:通过 API 动态加载微应用地址
json
// config/micro-apps.json
{
"task-center": {
"url": "https://cdn.example.com/task-center/v1.2.3/remoteEntry.js",
"enabled": true,
"grayUsers": ["user123", "admin"]
}
}
八、性能与安全考量
1. 性能优化
| 问题 | 解决方案 |
|---|---|
| 首屏加载慢 | Shell 预加载关键微应用(<link rel="prefetch">) |
| 重复请求 | 共享 HttpClient 实例(通过 Module Federation 暴露) |
| Bundle 过大 | 启用 Webpack SplitChunks + DevUI 按需引入 |
2. 安全加固
- CSP 策略 :限制
script-src仅允许可信 CDN - 沙箱隔离:微应用运行在 iframe(极端场景)
- 权限校验:Shell 路由守卫验证微应用访问权限
ts
// shell-routing.guard.ts
canLoad(route: Route): boolean {
const appId = route.data?.['appId'];
return this.permissionService.hasAccessToApp(appId);
}
九、常见问题与解决方案
| 问题 | 根因 | 解决方案 |
|---|---|---|
| DevUI 样式冲突 | 多个版本 DevUI 同时加载 | 强制 singleton + 统一版本 |
| 路由跳转失效 | 微应用使用自己的 RouterModule | 所有路由由 Shell 统一管理 |
| 状态不同步 | 微应用刷新后丢失全局状态 | 结合 localStorage + 初始化同步 |
| 构建失败 | Webpack 版本不一致 | 锁定 Nx + Angular + MF 插件版本 |
十、总结与演进方向
通过本篇实战,你已掌握:
- ✅ 基于 Module Federation 的微前端架构搭建
- ✅ DevUI 在微应用中的主题、组件、图标统一方案
- ✅ 跨应用状态管理与通信机制
- ✅ 独立 CI/CD 与灰度发布策略
🔮 未来演进:
- Module Federation 2.0:支持动态 remotes、共享 chunk 优化
- DevUI 微前端套件 :官方提供
@devui/mfe工具包- 低代码 + 微前端:业务人员可拖拽组合微应用模块
附录:推荐学习资源
- Webpack 官方 Module Federation 文档
- Nrwl Nx 微前端指南
- 华为云 DevUI 设计系统规范
- 《微前端实战》------ Michael Geers
1.MateChat:https://gitcode.com/DevCloudFE/MateChat
2.MateChat官网:https://matechat.gitcode.com
3.DevUI官网:https://devui.design/home