Wujie - transform Angular micro front-end project
Record how to use wujie to transform a micro front-end project based on angular
在学习无界这个微前端框架的时候,发现官方只提供了vue 和 react作为主应用的demo。作为Angular的使用者,是时候自己实践一遍如何从现有angular项目改造为微前端项目了!
项目工程搭建
为了模拟更真实的场景,我们首先利用脚手架生成一个Angular项目.
bash
ng new wujie-angular
默认cli会采用npm帮我们安装好依赖,由于我们采用pnpm 安装,所以打开我们的项目后,删除 'package.lock', 'node_modules'文件夹后。
bash
pnpm install
项目改造
目前我们的主项目文件都存在在src目录下,而我们的最终效果想在一个目录下管理我们的所有项目(主应用 + 子应用)。
最终效果:
apps/host-angular/
: Angular 主应用apps/vue-subapp/
: Vue 3 + Vite 子应用apps/react-subapp/
: React + Vite 子应用apps/ngx-wujie
: 无界angular组件库
首先在根目录下创建文件夹apps > host-angular
然后将src文件夹,public文件夹,tsconfig.app.json 和 tsconfig.spec.json拖到 host-angular文件夹下作为我们的主应用。
接下来是比较重要的一步,由于我更改了主应用的位置,所以所有相关的配置文件都要做出相应的更改。
首先是移动过的 tsconfig.app.json 和 tsconfig.spec.json 文件
json
"extends": "../../tsconfig.json" //原来是"extends": "./tsconfig.json"
然后是重头戏angular.json配置文件,需要更改的位置很多图中只展示了部分(想了解所有的话可以参考源码 code)。
将以上所有修改完毕后执行 ng serve 发现我们的项目成功启动了!(如果报错了一定是angular.json文件没有修改完全)项目改造基本完成了。
接着我们在apps目录下新建两个新的项目模拟我们的子应用。
bash
cd apps
pnpm create vite vue-subapp --template vue
pnpm create vite react-subapp --template react
然后安装依赖:
bash
//安装完两个项目此时在apps目录下
cd vue-subapp
pnpm install
cd ../
cd react-subapp
pnpm install
接着生成我们的ngx-wujie组件库
bash
ng generate library ngx-wujie
默认情况下cli会帮我们生成library到 projects文件夹下,我们依旧将他改到我们的apps目录下。更改过程同主应用就不再赘述了,执行命令 ng generate library ngx-wujie 成功打包证明我们迁移成功。
至此我们的准备工作完成了,此时每个项目都可以单独启动。整体的项目结构
wujie Angular组件的封装
由于官方只提供vue 和 react 组件,我们需要封装自己的angular 组件, 打开我们的 ngx-wujie library, 参考框架封装 对我们的 ngx-wujie.component.ts 改造。
首先在项目根目录下安装 wujie
bash
//wujie-angular 目录下
pnpm install wujie
新增 peerDependencies
json
"peerDependencies": {
"@angular/common": "^19.2.0",
"@angular/core": "^19.2.0",
"wujie": "^1.0.0"
},
ngx-wujie.component.ts 保留组件最核心的功能,后续再进行补充。
ts
import { Component, Input, ElementRef, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';
import { startApp, destroyApp } from 'wujie';
@Component({
selector: 'wujie-angular',
standalone: true,
template: `<div #container></div>`,
styles: ``
})
export class NgxWujieComponent implements AfterViewInit, OnDestroy {
@ViewChild('container', { static: true }) containerRef!: ElementRef<HTMLElement>;
@Input({ required: true }) name!: string;
@Input({ required: true }) url!: string;
ngAfterViewInit(): void {
this.start();
}
ngOnDestroy(): void {
this.destroy();
}
private start(): void {
if (!this.containerRef?.nativeElement || !this.name || !this.url) return;
startApp({
name: this.name,
url: this.url,
el: this.containerRef.nativeElement
});
}
private destroy(): void {
if (this.name) {
try {
destroyApp(this.name);
} catch {}
}
}
}
执行 ng build ngx-wujie 打包我们的组件, 修改根目录下 tsconfig.json文件, 新增配置
json
"paths": {
"ngx-wujie": [
"./dist/ngx-wujie"
]
},
Angular主应用中集成子应用
环境变量配置
打开我们的主应用,在 src 目录下新建environments 文件夹,分别创建 environment.ts和 environment.prod.ts文件
ts
export const environment = {
production: false,
VUE_SUBAPP_URL: 'http://localhost:4201/',
REACT_SUBAPP_URL: 'http://localhost:4202/'
};
//environment.ts prod文件改为对应的线上地址
同时我们需要对我们的主应用和子应用的package.json script脚本做相应的调整,
例如 vue-subapp
json
"scripts": {
"dev": "vite --port 4201",
"build": "vue-tsc -b && vite build",
"preview": "vite preview"
},
我们要保证运行端口与配置保持一致。
新建组件
主应用src 目录下新建 components 文件夹
分别创建 我们vue 和 react 应用组件
ts
//micro-vue.component.ts
import { Component } from '@angular/core';
import { environment } from '../../environments/environment';
import { NgxWujieComponent } from 'ngx-wujie';
@Component({
selector: 'micro-vue',
standalone: true,
imports: [NgxWujieComponent],
template: `
<wujie-angular
[name]="'vue-subapp'"
[url]="env.VUE_SUBAPP_URL"
/>
`
})
export class MicroVueComponent {
env = environment;
}
ts
//micro-react.component.ts
import { Component } from '@angular/core';
import { environment } from '../../environments/environment';
import { NgxWujieComponent } from 'ngx-wujie';
@Component({
selector: 'micro-react',
standalone: true,
imports: [NgxWujieComponent],
template: `
<wujie-angular
[name]="'vue-subapp'"
[url]="env.REACT_SUBAPP_URL"
/>
`
})
export class MicroReactComponent {
env = environment;
}
这样我们就完成了对子应用的 angular组件的封装。
配置路由
打开主应用 app.route.ts文件
ts
import { Routes } from '@angular/router';
import { MicroVueComponent } from './components/micro-vue.component';
import { MicroReactComponent } from './components/micro-react.component';
export const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'micro/vue' },
{ path: 'micro/vue', component: MicroVueComponent },
{ path: 'micro/react', component: MicroReactComponent }
];
我们做了对子应用组件的路由映射。
一切准备就绪, 接下来就是见证奇迹的时刻!
启动项目
打开三个新的命令行窗口分别执行
bash
cd apps/vue-subapp
pnpm dev
bash
cd apps/react-subapp
pnpm dev
bash
pnpm start
打开 http://localhost:4200/ 你会发现我们的主应用成功加载了vue子应用。
当然更改url http://localhost:4200/micro/react 也可以成功加载react子应用。
至此我们成功的用无界构建出了简版以angular项目为主应用的微前端项目。
pnpm + turbo
在开发环境下,大家可能觉得每次都要打开3个终端,分别执行启动命令,过于繁琐了,有没有好的办法可以让我一次命令就可以启动所有的项目呢 ? 当然有!
在根目录下:
新建 pnpm-workspace.yaml
yaml
packages:
- apps/*
新建 turbo.json
json
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", "build/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"test": {
"dependsOn": ["build"],
"outputs": []
},
"lint": {
"outputs": []
}
}
}
package.json文件修改
json
{
"packageManager": "pnpm@10.15.0",
"scripts": {
"dev": "turbo run dev --parallel --filter=!ngx-wujie",
},
}
apps目录下还有 ngx-wujie 项目,我们将他排除
安装 turbo
bash
pnpm add -D turbo@latest -w
如果安装失败,删除 node_modules
与 pnpm-lock.yaml
后 pnpm install
再试
最后在终端执行 turbo
bash
pnpm dev
我们的三个应用同时启动了!
解释一下如何做到的:
pnpm dev 执行根目录的脚本 turbo run dev --parallel 被调用,--parallel 参数让 Turborepo 并行执行所有找到的 dev 脚本。
Turborepo 扫描工作空间(pnpm-workspace.yaml),找到所有有 dev 脚本的项目, 并行执行脚本。
Summary
我们实现了:
- Angular 封装 Wujie 组件(精简版,后续持续集成wujie功能并打包发布到npm)
- Angualr 主应用接入 Vue/React 子应用
- 迁移 Monorepo 并实现
pnpm dev
并行开发
总体感觉下来基于无界改造项目可以说是很简单了。
