背景
首先,前端技术日新月异,从最初的jQuery,Ext.js,Ajax等技术,到近几年AngularJS,Angular,Vue,React等热门框架的出现,技术框架层出不穷,为了解决遗留系统迁移的问题,我们不得不考虑微服务架构,不重写原有系统,同时可以开发新的业务,是一个相当有吸引力的特性,而且对技术人员来说,也是一件相当不错的事情。人生苦短,请尽量不重写。
其次,随着业务发展,开发变得越来越复杂。新增,修改某个功能等操作,都需要重新部署整个系统,任意一个模块的问题,都有可能引起整个系统的崩溃等问题。庞大的系统采用微服务架构,将单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用可以实现独立开发、独立部署,减少部署时间,以及引起系统崩溃的原因。同时它们也可以进行并行开发——这些组件可以通过NPM、Git TagGit来进行管理。
最后,对大部分公司和团队来说,如果我们前期选定Angular,大概率我们将继续使用原有的框架,毕竟已经拥有大量成熟的基础设施。但是随着市场的变化,我们不得不考虑增加技术栈,更好的迎合市场,即微服务架构。微服务架构并不只是为了在架构上好看,还可以提升开发效率,尤其是庞大的应用系统,由单一应用拆分为多个小型前端应用,每个应用可以实现独立开发和独立部署,项目维护起来也会变得容易很多。
Micro-app使用说明
下面是以Angular为基座,默认基座的路由为history模式,Vue为子应用的使用:
基座应用,也叫主应用
1.安装依赖
npm install @micro-zoe/micro-app -S
2.main.ts文件引入
import microApp from '@micro-zoe/micro-app';
microApp.start({
disableScopecss: true // 禁用样式隔离可以提升页面渲染速度,在此之前,请确保各应用之间样式不会相互污染
});
3. 创建主应用入口文件夹,在src文件中,新建practice文件夹,在页面中嵌入子应用
index.component.html
<button nz-button (click)="onSendMessage()">下发消息</button>
<micro-app #microApp
*ngIf="mode == 'development'"
name="app1"
url="http://localhost:8080"
[data]="data"
(created)="onCreated($event)"
(mounted)="onMounted($event)"
(unmount)="onUnmount($event)"
(error)="onError($event)"
(datachange)="onHandleDataChange($evnet)"
baseroute="/index/practice">
</micro-app>
mode 配置不同的环境变量
url 根据环境不同配置URL地址
data 初始化给子应用的数据;只接受对象类型,采用严格对比(===),当传入新的data对象时会重新发送
index.component.ts
import { Component, OnInit } from "@angular/core";
import { MicroAppService } from "src/app/service/microapp.service";
import { environment } from "src/environments/environment";
@Component({
selector: 'app-index',
templateUrl: './index.component.html',
})
export class IndexComponent implements OnInit {
public mode: string = environment.mode;
data: any;
constructor(
private microAppService: MicroAppService,
) { }
ngOnInit() {
this.data = {
id: '111',
name: 'test',
}
}
onCreated(e) {
console.log('onCreated', e);
}
onBeforemount(e) {
console.log('onBeforemount', e);
}
onMounted(e) {
console.log('onMounted', e);
}
onUnmount(e) {
console.log('onUnmount', e);
}
onError(e) {
console.log('onError', e);
}
onSendMessage() {
this.microAppService.onSendData('新的数据');
}
merchantProjectCode() {
this.microAppService.onSendData('新的数据');
}
}
practice.routing.ts
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { IndexComponent } from "./index/index.component";
const routes: Routes = [
{
path: '',
component: IndexComponent
}
];
@NgModule({
declarations: [],
imports: [
RouterModule.forChild(routes)
]
})
export class PracticeRoutingModule{}
practice.module.ts
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
import { IndexComponent } from "./index/index.component";
import { PracticeRoutingModule } from "./practice.routing";
import { CommonModule } from "@angular/common";
@NgModule({
declarations: [IndexComponent],
imports: [
CommonModule,
PracticeRoutingModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class PracticeModule {}
提醒:Module模块必须引入CommonModule,否则将引起下面的报错。
4.路由导航
在app-routing.module.ts文件中增加子应用的入口
{
path: 'portal',
children: [
{
path: '**',
loadChildren: () => import('./pages/portal/portal.module').then((m) => m.PortalModule),
}
]
}
子应用
初始化一个vue的demo,具体实现过程我就不在这里展示了,直接进入到vue项目的钩子函数的调用及与基座应用的互动。
在主应用index.component.ts中,我们调用了一个服务MicroAppService,代码如下:
import { Injectable } from "@angular/core";
import microApp from "@micro-zoe/micro-app";
@Injectable({
providedIn: 'root'
})
export class MicroAppService {
onSendData(data) {
microApp.setData('app1', { type: 'send', data });
}
}
data属性用来初始化给子应用数据
比如:主应用ts模块中
ngOnInit() {
this.data = {
id: '111',
name: 'test',
}
}
在vue子应用中,在onMounted函数中
const data = (window as any).microApp.getData();
console.log('getData', data)
主应用通知子应用,根据需求采用两种不同的传入方式:
第一种:
// 主应用
this.microAppService.onSendData('新的数据')
// 子应用
onMounted(() => {
(window as any).microApp.addDataListener(e => {
console.log('刷新列表页面', e)
})
});
第二种:
// 主应用
this.microAppService.onSendData({type: '主应用通知子应用', data: '刷新列表'});
// 子应用
onMounted(() => {
(window as any).microApp.addDataListener(e => {
console.log('刷新列表页面', e)
})
});
子应用给主应用发送通知,代码如下:
// 子应用的触发事件
// dispatch只接收对象作为参数
(window as any).microApp.dispatch({ type: "子应用发送的数据"})
// 主应用接收事件
onHandleDataChange(e) {
console.log('datachange', e.detail.data)
}
总结
以上demo是总结的开发过程,主要陈述了以Angular为基座应用和Vue为子应用的使用方式,从依赖安装到主应用与子应用的互动,我们选择Micro-App作为实现方案,Micro-App是当下最火、讨论热度最高,使用起来最方便的技术栈。