angular+qiankun+single-spa的微前端配置
'# angular+qiankun+single-spa的微前端配置
一、背景与问题
在大型企业级应用开发中,微前端架构已成为解决复杂业务场景的常用方案。传统单体应用存在以下几个核心问题:
- 功能模块高度耦合,导致重构成本高
- 多团队协作时版本管理困难
- 技术栈统一性差,导致开发效率下降
- 系统扩展性受限
为解决这些问题,我们引入了qiankun+single-spa的组合方案。这个方案结合了qiankun的容器化管理和single-spa的生命周期控制能力,为Angular应用提供了灵活的微前端架构。
二、基本原理
1. qiankun的运行机制
qiankun通过以下核心机制实现微前端集成:
- 子应用注册:通过registerMicroApps注册子应用
- 沙箱机制:通过iframe沙箱隔离子应用环境
- 生命周期钩子:提供beforeLoad, beforeMount等钩子函数
- 通信机制:通过postMessage实现父子应用通信
2. single-spa的运行机制
single-spa通过以下核心机制实现微前端集成:
- 应用注册:通过registerApplication注册子应用
- 生命周期钩子:提供bootstrap, mount, unmount等钩子函数
- 路由管理:通过hash或history模式管理子应用路由
- 依赖注入:支持通过window对象暴露全局变量
3. Angular与微前端的结合
Angular应用需要通过以下方式适配微前端:
- 自定义激活规则:通过activeRule定义子应用的路由规则
- 生命周期管理:实现Angular的生命周期钩子与single-spa的生命周期同步
- 全局状态管理:通过Angular的service暴露全局状态
三、环境准备
1. 开发环境要求
# 安装依赖
npm install -g @angular/cli
npm install qiankun single-spa2. 项目结构规划
microfrontends/
├── main-app/ # 主应用
│ ├── src/
│ │ └── main.ts
│ └── package.json
├── sub-app1/ # 子应用1
│ ├── src/
│ │ └── main.ts
│ └── package.json
├── sub-app2/ # 子应用2
│ ├── src/
│ │ └── main.ts
│ └── package.json
└── package.json四、核心实现
1. 主应用配置(qiankun方式)
// main-app/src/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import * as qiankun from 'qiankun';
// angular应用的启动逻辑
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
// qiankun容器化配置
qiankun.registerMicroApps([
{
name: 'sub-app1',
entry: '//localhost:8081',
activeRule: '/sub-app1',
},
{
name: 'sub-app2',
entry: '//localhost:8082',
activeRule: '/sub-app2',
},
]);
qiankun.start({
prefetch: true,
useHash: true,
});关键代码解释:
registerMicroApps方法用于注册子应用activeRule定义了子应用的激活规则start方法启动qiankun容器prefetch选项开启预加载功能
2. 子应用配置(single-spa方式)
// sub-app1/src/main.ts
import { registerApplication, start } from 'single-spa';
import { angularApp } from './angular-app';
registerApplication(
'sub-app1',
() => angularApp,
(match) => match && match.includes('/sub-app1')
);
start();关键代码解释:
registerApplication方法注册子应用angularApp是Angular应用的启动函数match函数定义了子应用的匹配规则
3. Angular应用适配
// sub-app1/src/angular-app.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
export function angularApp() {
return platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
}关键代码解释:
- 导出的angularApp函数作为single-spa的入口
- 使用Angular的platformBrowserDynamic启动应用
五、完整案例
1. 项目结构
microfrontends/
├── main-app/ # 主应用
│ ├── src/
│ │ └── main.ts
│ └── package.json
├── sub-app1/ # 子应用1
│ ├── src/
│ │ └── main.ts
│ └── package.json
├── sub-app2/ # 子应用2
│ ├── src/
│ │ └── main.ts
│ └── package.json
└── package.json2. 主应用配置
// main-app/src/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import * as qiankun from 'qiankun';
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
qiankun.registerMicroApps([
{
name: 'sub-app1',
entry: '//localhost:8081',
activeRule: '/sub-app1',
},
{
name: 'sub-app2',
entry: '//localhost:8082',
activeRule: '/sub-app2',
},
]);
qiankun.start({
prefetch: true,
useHash: true,
});3. 子应用配置
// sub-app1/src/main.ts
import { registerApplication, start } from 'single-spa';
import { angularApp } from './angular-app';
registerApplication(
'sub-app1',
() => angularApp,
(match) => match && match.includes('/sub-app1')
);
start();4. Angular应用适配
// sub-app1/src/angular-app.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
export function angularApp() {
return platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
}六、源码解析
1. qiankun的容器化机制
qiankun通过创建iframe来隔离子应用,其核心代码如下:
// qiankun源码片段
function createIframe(options) {
const iframe = document.createElement('iframe');
iframe.src = options.entry;
iframe.style.display = 'none';
document.body.appendChild(iframe);
return iframe;
}关键点:
- iframe隔离了子应用的运行环境
- 通过postMessage进行跨域通信
- 沙箱机制防止子应用修改主应用环境
2. single-spa的生命周期管理
single-spa通过以下代码管理子应用生命周期:
// single-spa源码片段
function registerApplication(name, lifecycle, activeWhen) {
const app = {
name,
lifecycle,
activeWhen
};
registry.push(app);
}关键点:
- lifecycle函数包含bootstrap, mount, unmount等钩子
- activeWhen函数决定何时激活子应用
- 自动处理路由匹配和子应用挂载
七、进阶使用
1. 路由管理
// 主应用路由配置
const routes: Routes = [
{ path: 'sub-app1', loadChildren: () => import('./sub-app1.module').then(m => m.SubApp1Module) },
{ path: 'sub-app2', loadChildren: () => import('./sub-app2.module').then(m => m.SubApp2Module) },
];2. 全局状态管理
// 全局状态服务
@Injectable({
providedIn: 'root'
})
export class GlobalStateService {
private state: { [key: string]: any } = {};
set(key: string, value: any) {
this.state[key] = value;
}
get(key: string) {
return this.state[key];
}
}3. 跨应用通信
// 主应用通信
window.addEventListener('message', (event) => {
if (event.origin !== 'http://localhost:8081') return;
console.log('Received from sub-app1:', event.data);
});八、性能与工程实践
1. 性能优化
- 懒加载子应用:使用
prefetch选项预加载子应用资源 - 资源压缩:使用Webpack的TerserPlugin进行代码压缩
- 缓存策略:为子应用设置Cache-Control头
- 路由预处理:在主应用中预处理子应用的路由规则
2. 安全措施
- 跨域验证:确保子应用的origin与主应用一致
- XSS防护:对子应用的DOM进行安全检查
- CSRF防护:为敏感操作添加CSRF令牌
- 权限控制:在主应用中进行访问权限校验
3. 异常处理
// 异常处理中间件
qiankun.onGlobalError((err) => {
console.error('Global error in microfrontends:', err);
// 记录错误日志
// 通知运维系统
});九、常见问题与踩坑
1. 子应用加载失败
错误现象:子应用页面空白或报错404
解决方案:
- 检查子应用的entry是否正确
- 确保子应用的publicPath配置正确
- 检查服务器是否正确配置了CORS头
2. 生命周期钩子未执行
错误现象:子应用未正确初始化
解决方案:
- 确保子应用的入口函数正确导出
- 检查single-spa的registerApplication配置
- 确认子应用的路由规则匹配正确
3. 跨域通信问题
错误现象:子应用无法与主应用通信
解决方案:
- 在主应用的nginx配置中添加
add_header 'Access-Control-Allow-Origin' '*'; - 确保子应用的CORS配置正确
- 使用
postMessage进行安全通信
十、最佳实践
1. 分层架构设计
├── shared/ # 公共模块
├── core/ # 核心业务模块
├── microfrontends/ # 微前端模块
│ ├── main-app/ # 主应用
│ ├── sub-app1/ # 子应用1
│ └── sub-app2/ # 子应用2
└── services/ # 服务层2. 资源管理策略
- 使用Webpack的SplitChunksPlugin分离公共代码
- 为子应用设置独立的chunk命名规则
- 使用Webpack的CodeSplitting进行按需加载
3. 开发规范
- 所有子应用必须包含完整的Angular配置
- 禁止在子应用中直接操作主应用的DOM
- 所有通信必须通过postMessage进行
十一、总结
angular+qiankun+single-spa的微前端配置方案,为复杂业务场景提供了灵活的解决方案。通过qiankun的容器化管理和single-spa的生命周期控制,实现了多技术栈应用的无缝集成。在实际应用中,需要根据具体业务需求选择合适的配置方式,并注意处理好跨应用通信、安全防护和性能优化等问题。
该方案特别适合以下场景:
- 多团队协作开发的大型项目
- 需要快速迭代的业务模块
- 技术栈需要统一但又保持灵活性的系统
但需要注意,对于小型项目或技术栈统一的项目,使用微前端会增加开发复杂度,需要权衡利弊。在实施过程中,建议从简单的子应用开始,逐步扩展,同时建立完善的文档和规范,确保团队协作的顺畅。
评论已关闭