一、配置环境
安装nodejs(16.13.0)
查看node
win + r 打开运行窗口输入 cmd 回车,打开控制台
分别输入 node -v 和 npm -v 查看是否安装成功-(出现版本号表示安装成功,如果失败从头操作)
升级 npm 包管理器的版本-(16.13.0 node自带的npm包管理器版本较低)
npm i npm@8.19.2 -g
全局安装angular脚手架
npm i @angular/cli@13.3.0 -g
查看是否安装成功
ng v
二、初始化项目-(创建主微应用)
新建一个文件夹-(随意命名,我这里叫mirco-test-pro)
在路径栏输入 cmd 按下 回车 进入控制台
创建一个主应用
ng new micro-main-app --skip-install (蓝色参数可选,表示初始化项目时跳过依赖安装)
创建两个子应用
以同样的方式创建两个子应用
创建子应用1: ng new micro-child-app1 --skip-install
创建子应用2: ng new micro-child-app2 --skip-install
此时文件夹下有三个应用
三、配置主应用
使用idea打开包含三个应用的主文件夹,分别进入三个应用的根目录安装依赖
npm i
在主应用中安装qiankun和qiankun-ng-common
npm i qiankun@2.6.3 -S
npm i qiankun-ng-common@0.0.2 --force
在主应用中注册微应用(在app.component.ts)中注册
constructor(private router: Router) {
}
import {registerMicroApps, setDefaultMountApp, start} from "qiankun";
ngOnInit() {
registerMicroApps([
{
name: 'micro-child-app1', // 子应用名字
entry: '//localhost:5000', // 子应用的入口
container: '#child1-container', // 挂载子应用时的id选择器出口
activeRule: '/micro-child-app1', // 匹配路径
props:{data:this.router}
}
]);
setDefaultMountApp('/micro-child-app1'); // 默认挂载子应用1
}
ngAfterViewInit(): void {
start();
}
const routes: Routes = [
{
path: 'micro-child-app1', // 微应用1的入口
component: EmptyComponent
},
{
path: '**',
component: EmptyComponent // 配置默认路由,避免路由到子项目报错
}
];
四、配置子应用
子应用1
1. 在 src 目录新增 public-path.js 文件,内容为:
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
2. 在子应用的app.routing-module.ts中
+ import { APP_BASE_HREF } from '@angular/common';
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
// @ts-ignore
+ providers: [{ provide: APP_BASE_HREF, useValue: window.__POWERED_BY_QIANKUN__ ? '/micro-child-app1' : '/' }]
})
3. 修改入口文件,src/main.ts 文件
import './public-path';
import { enableProdMode, NgModuleRef } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { environment } from './environments/environment';
import {AppModule} from "./app/app.module";
if (environment.production) {
enableProdMode();
}
let app: void | NgModuleRef<AppModule>;
async function render() {
app = await platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
}
if (!(window as any).__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap(props: Object) {
// console.log(props[0].data);
}
export async function mount(props: Object) {
render();
}
export async function unmount(props: Object) {
// console.log(props);
// @ts-ignore
app.destroy();
}
4. 修改 webpack 打包配置
安装依赖
npm i @angular-builders/custom-webpack@13.1.0 -D
在根目录增加 extra-webpack.config.js,内容为
const singleSpaAngularWebpack = require('single-spa-angular/lib/webpack').default;
module.exports = (config, options) => {
const singleSpaWebpackConfig = singleSpaAngularWebpack(config, options);
const singleSpaConfig = {
output: {
// 微应用的包名,这里与主应用中注册的微应用名称一致
library: "micro-child-app1", //这里要改成自己的应用名
// 将你的 library 暴露为所有的模块定义下都可运行的方式
libraryTarget: "umd",
},
};
// Feel free to modify this webpack config however you'd like to
return singleSpaWebpackConfig;
};
修改 angular.json,将 [packageName] > architect > build > builder 和 [packageName] > architect > serve > builder 的值改为我们安装的插件,将我们的打包配置文件加入到 [packageName] > architect > build > options
- "builder": "@angular-devkit/build-angular:browser",
+ "builder": "@angular-builders/custom-webpack:browser",
"options": {
+ "customWebpackConfig": {
+ "path": "extra-webpack.config.js",
+ "libraryName": "micro-child-app1",
+ "libraryTarget": "umd"
+ }
+ "deployUrl": "http://localhost:5000/"
}
- "builder": "@angular-devkit/build-angular:dev-server",
+ "builder": "@angular-builders/custom-webpack:dev-server",
5. 解决zone.js问题
1. 在主应用中注入zone.js
// micro-main-app/src/main.ts
// 为 Angular 微应用所做的 zone 包注入
import "zone.js/dist/zone";
2. 将子应用的 src/polyfills.ts 里面的引入 zone.js 代码删掉。
3. 在子应用的 src/index.html 里面的 标签加上下面内容,子应用独立访问时使用。
6. 修正 ng build 打包报错问题,修改 tsconfig.json 文件
- "target": "es2015",
+ "target": "es5",
+ "typeRoots": [
+ "node_modules/@types"
+ ],
7. 防止子应用和主应用的根组件选择器产生冲突,建议各自起名字
子应用的根组件
子应用的index.html
8. 安装single-spa
npm i single-spa -S
9. 添加 single-spa-angular
ng add single-spa-angular@6.1.0
10 . main.single-spa.ts 中需要加入
在生成 single-spa 配置后,我们需要进行一些 qiankun 的接入配置。我们在 Angular 微应用的入口文件 main.single-spa.ts 中,导出 qiankun 主应用所需要的三个生命周期钩子函数,代码实现如下:
import { enableProdMode, NgZone } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { Router, NavigationStart } from '@angular/router';
import { singleSpaAngular, getSingleSpaExtraProviders } from 'single-spa-angular';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { singleSpaPropsSubject } from './single-spa/single-spa-props';
if (environment.production) {
enableProdMode();
}
// 微应用单独启动时运行
if (!(window as any).__POWERED_BY_QIANKUN__) {
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
}
const lifecycles = singleSpaAngular({
bootstrapFunction: singleSpaProps => {
singleSpaPropsSubject.next(singleSpaProps);
return platformBrowserDynamic(getSingleSpaExtraProviders()).bootstrapModule(AppModule);
},
template: '<micro-child-app1 />',
Router,
NavigationStart,
NgZone,
});
export const bootstrap = lifecycles.bootstrap;
export const mount = lifecycles.mount;
export const unmount = lifecycles.unmount;
!!!注意事项:其他子应用均按照子应用1参考配置
子应用启动后无法正常显示网页
五、界面展示
主应用相关模板
子应用相关模板
启动子应用和主应用
相关界面
六、主应用中无法正常跳转子应用中的路由问题:
解决:需要把对应子应用中的路由配置在主应用中的app.routing.module.ts中进行声明注册