实践日期:2023-03-04
ng version
Angular CLI: 15.2.1
Node: 18.14.2
Package Manager: npm 9.5.0
OS: win32 x64
设置npm镜像源
npm config set registry https://registry.npmmirror.com/
安装yarn并设置yarn镜像源,实践版本:yarn@1.22.19
npm i -g yarn
yarn config set registry https://registry.npmmirror.com/
yarn config set sass_binary_site https://npmmirror.com/mirrors/node-sass/
yarn config set canvas_binary_host_mirror https://npmmirror.com/mirrors/canvas/
创建项目,命名为main,设置样式格式为css,启用路由,设置包管理器为yarn
添加项目模板ng-alain,实践版本:ng-alain@15.1.0,过程中ng-alain的询问全部采用默认选择
安装qiankun,实践版本:qiankun@2.10.2
ng new main --style less --routing --package-manager yarn
cd main
ng add ng-alain
yarn add qiankun
创建微服务容器组件:src/app/routes/qiankun-container/qiankun-container.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'qiankun-container',
template: '<div id="qiankun-container-{{containerId}}"></div>'
})
export class QiankunContainerComponent implements OnInit {
containerId = 'default';
constructor(private route: ActivatedRoute) {}
ngOnInit(): void {
this.containerId = this.route.snapshot.data?.['containerId'];
}
}
设置路由:src/app/routes/routes-routing.module.ts
import { QiankunContainerComponent } from './qiankun-container/qiankun-container.component';
canActivate: [startPageGuard, SimpleGuard],
children: [ // 以下是新增内容
{
path: 'micro1',
children: [
{
path: '**',
component: QiankunContainerComponent,
data: { containerId: 'micro1' },
},
],
},
设置菜单:src/app/core/startup/startup.service.ts
children: [
{
text: 'Dashboard',
link: '/dashboard',
icon: { type: 'icon', value: 'appstore' }
} // 以下是新增内容
,
{
text: 'Micro1',
icon: { type: 'icon', value: 'appstore' },
children: [
{
text: '主导航',
group: true,
hideInBreadcrumb: true,
children: [
{
text: '仪表盘',
icon: 'anticon-dashboard',
children: [
{
text: '默认页',
link: '/micro1/dashboard/v1',
},
{
text: '分析页',
link: '/micro1/dashboard/analysis',
},
{
text: '监控页',
link: '/micro1/dashboard/monitor',
},
{
text: '工作台',
link: '/micro1/dashboard/workplace',
}
]
},
{
text: '小部件',
link: '/micro1/widgets',
icon: 'anticon-appstore',
}
]
},
{
text: 'Alain',
group: true,
hideInBreadcrumb: true,
children: [
{
text: '样式',
icon: 'anticon-info',
children: [
{
text: '字体排印',
link: '/micro1/style/typography',
},
{
text: '瀑布流',
link: '/micro1/style/gridmasonry',
},
{
text: '色彩',
link: '/micro1/style/colors',
}
]
},
{
text: 'Delon 类库',
icon: 'anticon-bulb',
children: [
{
text: '动态表单',
link: '/micro1/delon/form',
},
{
text: '简易表格',
link: '/micro1/delon/st',
},
{
text: '工具集',
link: '/micro1/delon/util',
},
{
text: '打印',
link: '/micro1/delon/print',
},
{
text: '二维码',
link: '/micro1/delon/qr',
},
{
text: '基于角色访问控制',
link: '/micro1/delon/acl',
},
{
text: '路由守卫',
link: '/micro1/delon/guard',
},
{
text: '字典缓存',
link: '/micro1/delon/cache',
},
{
text: '下载文件',
link: '/micro1/delon/downfile',
},
{
text: 'Excel操作',
link: '/micro1/delon/xlsx',
},
{
text: '本地解压缩',
link: '/micro1/delon/zip',
}
]
}
]
},
{
text: 'Antd Pro',
group: true,
hideInBreadcrumb: true,
children: [
{
text: '表单页',
link: '/micro1/pro/form',
icon: 'anticon-edit',
children: [
{
text: '基础表单',
link: '/micro1/pro/form/basic-form',
},
{
text: '分步表单',
link: '/micro1/pro/form/step-form',
},
{
text: '高级表单',
link: '/micro1/pro/form/advanced-form',
}
]
},
{
text: '列表页',
icon: 'anticon-appstore',
children: [
{
text: '查询表格',
link: '/micro1/pro/list/table-list',
},
{
text: '标准列表',
link: '/micro1/pro/list/basic-list',
},
{
text: '卡片列表',
link: '/micro1/pro/list/card-list',
},
{
text: '搜索列表',
children: [
{
text: '搜索列表(文章)',
link: '/micro1/pro/list/articles',
},
{
text: '搜索列表(项目)',
link: '/micro1/pro/list/projects',
},
{
text: '搜索列表(应用)',
link: '/micro1/pro/list/applications',
}
]
}
]
},
{
text: '详情页',
icon: 'anticon-profile',
children: [
{
text: '基础详情页',
link: '/micro1/pro/profile/basic',
},
{
text: '高级详情页',
link: '/micro1/pro/profile/advanced',
}
]
},
{
text: '结果页',
icon: 'anticon-check-circle',
children: [
{
text: '成功页',
link: '/micro1/pro/result/success',
},
{
text: '失败页',
link: '/micro1/pro/result/fail',
}
]
},
{
text: '异常页',
link: '/micro1/',
icon: 'anticon-exception',
children: [
{
text: '403',
link: '/micro1/exception/403',
},
{
text: '404',
link: '/micro1/exception/404',
},
{
text: '500',
link: '/micro1/exception/500',
}
]
},
{
text: '个人页',
icon: 'anticon-user',
children: [
{
text: '个人中心',
link: '/micro1/pro/account/center',
},
{
text: '个人设置',
link: '/micro1/pro/account/settings',
}
]
}
]
},
{
text: '更多',
group: true,
hideInBreadcrumb: true,
children: [
{
text: '报表',
icon: 'anticon-cloud',
children: [
{
text: '全屏关系图',
link: '/micro1/data-v/relation',
}
]
},
{
text: '扩展',
link: '/micro1/extras',
icon: 'anticon-link',
children: [
{
text: '帮助中心',
link: '/micro1/extras/helpcenter',
},
{
text: '设置',
link: '/micro1/extras/settings',
},
{
text: '门店',
link: '/micro1/extras/poi',
}
]
}
]
}
]
},
注册微应用并启动:src/app/app.component.ts
import { registerMicroApps, start } from 'qiankun';
constructor(
el: ElementRef,
renderer: Renderer2,
private router: Router,
private titleSrv: TitleService,
private modalSrv: NzModalService
) { // 以下是新增内容
registerMicroApps([
{
name: 'micro1',
entry: '/micro1/',
container: '#qiankun-container-micro1',
activeRule: 'main/#/micro1'
}
]);
start();
设置基路径和服务路径:angular.json
{
"projects": {
"main": {
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"baseHref": "/main/", // 新增该行
},
},
"serve": {
"defaultConfiguration": "development",
"options": {
"servePath": "main", // 新增该行
设置代理配置:proxy.conf.js
module.exports = { // 以下是新增内容
'/micro1/': {
target: 'http://localhost:4201/',
},
启动应用
yarn start
克隆项目,实践版本:SHA-1: 6a8a939b580cc717ee779e71222055358e0125a8
git clone --depth=1 https://github.com/ng-alain/ng-alain.git micro1
修改项目名称:angular.json
projects/ng-alain/architect节点里的ng-alain:改为micro1:,批量改时需要包含冒号,共6处
projects节点下的ng-alain改为micro1
cli节点里的ng-alain保持原状
{
"projects": {
"ng-alain": { // ng-alain改为micro1
},
"cli": {
"schematicCollections": [
"ng-alain" // 保持原状
修改包名称:package.json
{
"name": "ng-alain", // ng-alain改为micro1
修改选择器前缀:angular.json
{
"projects": {
"ng-alain": {
"prefix": "app", // app改为micro1
修改应用根标签
将项目中的app-root改为micro1-root,5个文件中共6处
修改应用根标签是必要的,否则会与主应用根标签(app-root)混淆,导致主应用异常
e2e/src/app.po.ts
src/index.html
src/app/app.component.ts
src/assets/style.compact.css
src/assets/style.dark.css
添加项目模板single-spa-angular,实践版本:single-spa-angular@8.0.1
过程中会出现3个问题,如下回答
安装依赖,以满足single-spa-angular的需要
cd micro1
ng add single-spa-angular
Would you like to proceed? (Y/n) Y
Does your application use Angular routing? (Y/n) Y
What port should your project run on? (4200) 4201
yarn install
移除预加载(preloader)层:src/index.html
微应用在主应用中启动时,会出现预加载层遮罩整个窗口,但是微应用启动完成后,预加载层不消失
预加载组件功能使用类选择器document.querySelector(".preloader")定位预加载层
微应用能定位到主应用的预加载层,却不能定位到自己的预加载层,无法控制其消失
<micro1-root></micro1-root>
<!-- 删除或注释掉div.preloader
<div class="preloader">
<div class="cs-loader">
<div class="cs-loader-inner">
<label> ●</label>
<label> ●</label>
<label> ●</label>
<label> ●</label>
<label> ●</label>
<label> ●</label>
</div>
</div>
</div>
-->
设置路由:src/app/routes/routes-routing.module.ts
不包裹基础布局组件LayoutBasicComponent,主应用负责控制布局
const routes: Routes = [
{
path: '',
component: LayoutBasicComponent, // 删除或注释掉该行
设置基路径、部署路径和服务路径:angular.json
{
"projects": {
"main": {
"architect": {
"build": {
"options": {
"baseHref": "/micro1/", // 新增该行
"deployUrl": "http://localhost:4201/" // "http://localhost:4201/"改为"/micro1/"
},
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"servePath": "micro1", // 新增该行
设置基路径:src/app/routes/routes-routing.module.ts
import { APP_BASE_HREF } from '@angular/common';
@NgModule({
providers: [PreloadOptionalModules, { provide: APP_BASE_HREF, useValue: '/micro1' }], // 设置APP_BASE_HREF
设置基路径:src/environments/environment.ts、environment.prod.ts
api: {
baseUrl: './', // './'改为'/micro1/'
设置基路径:src/assets/tmp/app-data.json
"avatar": "./assets/tmp/img/avatar.jpg", // ./assets/改为/micro1/assets/
设置基路径:src/app/layout/basic/basic.component.ts
将文件中的`./assets/改为`${this.baseUrl}assets/,共2处
export class LayoutBasicComponent {
baseUrl = environment.api.baseUrl; // 新增该行
options: LayoutDefaultOptions = {
logoExpanded: `./assets/logo-full.svg`,
logoCollapsed: `./assets/logo.svg`
设置基路径:src/app/layout/basic/widgets/task.component.ts
将文件中的'./assets/改为baseUrl + 'assets/,共5处
import { environment } from '@env/environment';
<nz-avatar [nzSrc]="'./assets/tmp/img/1.png'"></nz-avatar>
<nz-avatar [nzSrc]="'./assets/tmp/img/2.png'"></nz-avatar>
<nz-avatar [nzSrc]="'./assets/tmp/img/3.png'"></nz-avatar>
<nz-avatar [nzSrc]="'./assets/tmp/img/4.png'"></nz-avatar>
<nz-avatar [nzSrc]="'./assets/tmp/img/5.png'"></nz-avatar>
export class HeaderTaskComponent { // 以下是新增内容
baseUrl = environment.api.baseUrl;
设置基路径:src/app/layout/passport/passport.component.ts
import { environment } from '@env/environment';
export class LayoutPassportComponent implements OnInit { // 以下是新增内容
baseUrl = environment.api.baseUrl;
设置基路径:src/app/layout/passport/passport.component.html
将文件中的"./assets/改为"{{baseUrl}}assets/,共1处
<img class="logo" src="./assets/logo-color.svg" />
设置基路径:src/app/routes/dashboard/v1/v1.component.ts
import { environment } from '@env/environment';
export class DashboardV1Component implements OnInit { // 以下是新增内容
baseUrl = environment.api.baseUrl;
设置基路径:src/app/routes/dashboard/v1/v1.component.html
将文件中的'./assets/改为baseUrl + 'assets/,共2处
<nz-avatar [nzSrc]="'./assets/tmp/img/' + item.avatar + '.png'"></nz-avatar>
<nz-avatar [nzSrc]="'./assets/tmp/img/' + item.avatar + '.png'"></nz-avatar>
设置基路径:src/app/routes/extras/settings/settings.component.ts
import { environment } from '@env/environment';
export class ExtrasSettingsComponent implements OnInit { // 以下是新增内容
baseUrl = environment.api.baseUrl;
设置基路径:src/app/routes/extras/settings/settings.component.html
将文件中的"./assets/改为"{{baseUrl}}assets/,共1处
<img src="./assets/tmp/img/avatar.jpg" style="width: 100%" />
设置基路径:src/app/routes/style/gridmasonry/gridmasonry.component.ts
import { environment } from '@env/environment';
export class GridMasonryComponent {
baseUrl = environment.api.baseUrl;
}
设置基路径:src/app/routes/style/gridmasonry/gridmasonry.component.html
将文件中的"assets/改为"{{baseUrl}}assets/,共10处
<img src="assets/tmp/img/bg1.jpg" alt="" />
<img src="assets/tmp/img/bg2.jpg" alt="" />
<img src="assets/tmp/img/bg3.jpg" alt="" />
<img src="assets/tmp/img/bg4.jpg" alt="" />
<img src="assets/tmp/img/bg5.jpg" alt="" />
<img src="assets/tmp/img/bg6.jpg" alt="" />
<img src="assets/tmp/img/bg7.jpg" alt="" />
<img src="assets/tmp/img/bg8.jpg" alt="" />
<img src="assets/tmp/img/bg9.jpg" alt="" />
<img src="assets/tmp/img/bg10.jpg" alt="" />
设置基路径:src/app/routes/widgets/widgets/widgets.component.ts
import { environment } from '@env/environment';
export class WidgetsComponent implements OnInit { // 以下是新增内容
baseUrl = environment.api.baseUrl;
设置基路径:src/app/routes/widgets/widgets/widgets.component.html
将文件中的"./assets/改为"{{baseUrl}}assets/,共3处
将文件中的('./assets/改为('{{baseUrl}}assets/,共1处
将文件中的'./assets/改为baseUrl + 'assets/,共3处
<img src="./assets/tmp/img/half-float-bg-1.jpg" />
<img class="p-sm" src="./assets/tmp/img/1.png" />
<div class="text-center bg-center py-lg text-white" style="background-image: url('./assets/tmp/img/bg9.jpg')">
<nz-avatar [nzSrc]="'./assets/tmp/img/1.png'"></nz-avatar>
<img class="img-fluid align-middle" src="./assets/tmp/img/bg1.jpg" alt="" />
<nz-avatar [nzSrc]="'./assets/tmp/img/' + item.avatar + '.png'"></nz-avatar>
<nz-avatar [nzSrc]="'./assets/tmp/img/' + item.avatar + '.png'"></nz-avatar>
关闭操作指南:src/app/routes/dashboard/v1/v1.component.ts
setTimeout(() => this.genOnboarding(), 1000); // 删除或注释掉该行
启动应用
yarn run serve:single-spa:micro1
跳转微应用:http://localhost:4200/main/#/micro1/dashboard/v1
基于qiankun搭建ng-alain15微前端项目示例实践_TodayCoding的博客-CSDN博客
ng-alain15-example · master · TodayCoding / Qiankun study examples · GitCode
基于qiankun搭建angular15微前端项目入门实践_TodayCoding的博客-CSDN博客
基于qiankun搭建angular15 hash URL微前端项目入门实践_TodayCoding的博客-CSDN博客
基于qiankun搭建ng-alain15微前端项目入门实践_TodayCoding的博客-CSDN博客
基于qiankun搭建vue3 webpack ts微前端项目入门实践_TodayCoding的博客-CSDN博客
基于qiankun搭建vue3 webpack ts无懒加载微前端项目入门实践_TodayCoding的博客-CSDN博客
基于qiankun搭建element plus webpack微前端项目入门实践_TodayCoding的博客-CSDN博客