angular18使用qiankun搭建微服务
在angular18版本中使用微服务。
需求
在angular18版本中使用微服务。
创建主应用
通过angular脚手架ng new demo_zhu 创建一个名为demo_zhu的angular项目,正常装依赖使其可以运行,然后就可以配置主应用入口文件。
主应用配置
首先需要新建一个文件(如:qiankun-sub)作为入口文件,html内给一个标签就可以了
<div id="qiankun" class="qiankun" style="width: 100%; height: 100%"> </div>ts文件内写qiankun的注册方法和启动,如此主应用就配置好了。
import { registerMicroApps, start } from 'qiankun'; registerMicroApps([ { name: 'demo_zi',//子应用的项目名称 entry: '//localhost:4300',// 本地调试(发布需改为实际地址) container: '#containerqiankun',//html的id名 activeRule: '/qiankun',//主应用跳转子应用的主路径 props: this.msg//msg可以作为给子应用传输的数据 }, ],{ beforeLoad: [ (app) => { console.log('[LifeCycle] before load %c%s', 'color: green;', app.name) return Promise.resolve() }, ], beforeMount: [ (app) => { console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name) return Promise.resolve() }, ], afterUnmount: [ (app) => { console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name) return Promise.resolve() }, ], }); // 启动 qiankun start();
配置子应用
新建一个名为demo_zi的angular项目 。
由于angular18版本已经没有module文件,需要手动创建一个app.module文件以用来做main.ts内的一些配置用。我按照官网使用single-spa-angular插件,在angular18不好用,所以新建了一个module文件。由于18版本都组件化了,所以要把app.component的standalone和imports给注释掉。
@Component({ selector: '#angular18 app-root', // standalone: true, // imports: [RouterOutlet], templateUrl: './app.component.html', styleUrl: './app.component.css' })
app.module文件,如果app.component的standalone和imports不注释app.module文件使用就会报错。
import { NgModule, provideZoneChangeDetection } from '@angular/core'; import { AppComponent } from './app.component'; import { BrowserModule } from '@angular/platform-browser'; import { CeshiComponent } from './ceshi/ceshi.component'; import { AppRoutingModule } from './app-routing'; @NgModule({ declarations: [AppComponent,CeshiComponent], imports: [BrowserModule,AppRoutingModule], bootstrap: [AppComponent], providers: [] }) export class AppModule {}
修改main.ts文件内配置,这里需要使用app.module文件
import { AppModule } from './app/app.module'; import { NgModuleRef, NgZone, enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { environment } from './environments/environment'; let app: void | NgModuleRef<AppModule>; async function render(props?:any) { app = await platformBrowserDynamic() .bootstrapModule(AppModule,{ ngZone: (window as any).ngZone }) .catch((err) => console.error(err)); console.log(`子应用数据接收`,props); } if (!(window as any).__POWERED_BY_QIANKUN__) { render(); } if (environment.production) { enableProdMode(); } export async function bootstrap(props: Object) { console.log(props); } export async function mount(props: Object) { render(props); } export async function unmount(props: Object) { console.log(props); // @ts-ignore app.destroy(); }
安装
@angular-builders/custom-webpack插件 npm i @angular-builders/custom-webpack在根目录增加
custom-webpack.config.js文件,这一段和官网一样,内容是:const appName = require('./package.json').name; module.exports = { devServer: { headers: { 'Access-Control-Allow-Origin': '*', }, }, output: { library: `${appName}-[name]`, libraryTarget: 'umd', jsonpFunction: `webpackJsonp_${appName}`, // webpack 5 需要把 jsonpFunction 替换成 chunkLoadingGlobal }, };修改
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": "./custom-webpack.config.js" + } } ... - "builder": "@angular-devkit/build-angular:dev-server", + "builder": "@angular-builders/custom-webpack:dev-server",
修改配置文件package.json文件,将运行的端口号改为和主应用入口一致的端口"start": "ng serve --port 4300 --open" 。 "browser": "src/main.ts",改为 "main": "src/main.ts",
子应用的路由文件要加上@NgModule和export导出 。providers中/qiankun是需要跳转的路由,需要和主应用入口文件的路径一致。
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { CeshiComponent } from './ceshi/ceshi.component'; import { CeshiComponentTwo } from './ceshi copy/ceshi.component'; import { APP_BASE_HREF } from '@angular/common'; export const routes: Routes = [ { path: 'add', component: CeshiComponent}, { path: 'ceshi', component: CeshiComponentTwo }, { path: '**', redirectTo: '/add', pathMatch: 'full' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], providers: [{ provide: APP_BASE_HREF, useValue: (window as any).__POWERED_BY_QIANKUN__ ? '/qiankun' : '/' }] }) export class AppRoutingModule {}
问题
配置到这个地方基本上已经可以运行了。在主应用配置相应的跳转路由就可以了。
其中碰到了几个问题
1、跳转的时候路径会闪烁刷新或者直接报错说找不到路径,找了好几个方法都不好用。
2、跳转之后会报一个zone不存在问题,按照官网的方法在18版本也不行。
解决方法:
1、跳转到子应用的路由需要在主应用的路由配置里面添加完整的路由,子应用的路由文件内的providers中的路由一定要一致,否则也会导致路由闪烁。
2、在主应用的入口文件添加构造器,将ngZone 存放到window 里面。然后子应用的main文件中加进去
constructor(private ngZone: NgZone) { (window as any).ngZone = this.ngZone }let app: void | NgModuleRef<AppModule>; async function render(props?:any) { app = await platformBrowserDynamic() .bootstrapModule(AppModule,{ ngZone: (window as any).ngZone }) .catch((err) => console.error(err)); console.log(`子应用数据接收`,props); }
更多推荐
所有评论(0)