• 浅谈前端微服务背景及Micro-app的使用


    背景

            首先,前端技术日新月异,从最初的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文件引入

    1. import microApp from '@micro-zoe/micro-app';
    2. microApp.start({
    3. disableScopecss: true // 禁用样式隔离可以提升页面渲染速度,在此之前,请确保各应用之间样式不会相互污染
    4. });

    3. 创建主应用入口文件夹,在src文件中,新建practice文件夹,在页面中嵌入子应用

     index.component.html

    1. <button nz-button (click)="onSendMessage()">下发消息button>
    2. <micro-app #microApp
    3. *ngIf="mode == 'development'"
    4. name="app1"
    5. url="http://localhost:8080"
    6. [data]="data"
    7. (created)="onCreated($event)"
    8. (mounted)="onMounted($event)"
    9. (unmount)="onUnmount($event)"
    10. (error)="onError($event)"
    11. (datachange)="onHandleDataChange($evnet)"
    12. baseroute="/index/practice">
    13. micro-app>

    mode 配置不同的环境变量

    url 根据环境不同配置URL地址

    data 初始化给子应用的数据;只接受对象类型,采用严格对比(===),当传入新的data对象时会重新发送 

    index.component.ts

    1. import { Component, OnInit } from "@angular/core";
    2. import { MicroAppService } from "src/app/service/microapp.service";
    3. import { environment } from "src/environments/environment";
    4. @Component({
    5. selector: 'app-index',
    6. templateUrl: './index.component.html',
    7. })
    8. export class IndexComponent implements OnInit {
    9. public mode: string = environment.mode;
    10. data: any;
    11. constructor(
    12. private microAppService: MicroAppService,
    13. ) { }
    14. ngOnInit() {
    15. this.data = {
    16. id: '111',
    17. name: 'test',
    18. }
    19. }
    20. onCreated(e) {
    21. console.log('onCreated', e);
    22. }
    23. onBeforemount(e) {
    24. console.log('onBeforemount', e);
    25. }
    26. onMounted(e) {
    27. console.log('onMounted', e);
    28. }
    29. onUnmount(e) {
    30. console.log('onUnmount', e);
    31. }
    32. onError(e) {
    33. console.log('onError', e);
    34. }
    35. onSendMessage() {
    36. this.microAppService.onSendData('新的数据');
    37. }
    38. merchantProjectCode() {
    39. this.microAppService.onSendData('新的数据');
    40. }
    41. }

    practice.routing.ts

    1. import { NgModule } from "@angular/core";
    2. import { RouterModule, Routes } from "@angular/router";
    3. import { IndexComponent } from "./index/index.component";
    4. const routes: Routes = [
    5. {
    6. path: '',
    7. component: IndexComponent
    8. }
    9. ];
    10. @NgModule({
    11. declarations: [],
    12. imports: [
    13. RouterModule.forChild(routes)
    14. ]
    15. })
    16. export class PracticeRoutingModule{}

    practice.module.ts

    1. import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
    2. import { IndexComponent } from "./index/index.component";
    3. import { PracticeRoutingModule } from "./practice.routing";
    4. import { CommonModule } from "@angular/common";
    5. @NgModule({
    6. declarations: [IndexComponent],
    7. imports: [
    8. CommonModule,
    9. PracticeRoutingModule
    10. ],
    11. schemas: [CUSTOM_ELEMENTS_SCHEMA]
    12. })
    13. export class PracticeModule {}

    提醒:Module模块必须引入CommonModule,否则将引起下面的报错。

     4.路由导航

    在app-routing.module.ts文件中增加子应用的入口

    1. {
    2. path: 'portal',
    3. children: [
    4. {
    5. path: '**',
    6. loadChildren: () => import('./pages/portal/portal.module').then((m) => m.PortalModule),
    7. }
    8. ]
    9. }

    子应用

            初始化一个vue的demo,具体实现过程我就不在这里展示了,直接进入到vue项目的钩子函数的调用及与基座应用的互动。

      在主应用index.component.ts中,我们调用了一个服务MicroAppService,代码如下:

    1. import { Injectable } from "@angular/core";
    2. import microApp from "@micro-zoe/micro-app";
    3. @Injectable({
    4. providedIn: 'root'
    5. })
    6. export class MicroAppService {
    7. onSendData(data) {
    8. microApp.setData('app1', { type: 'send', data });
    9. }
    10. }

     data属性用来初始化给子应用数据

    比如:主应用ts模块中

    1. ngOnInit() {
    2. this.data = {
    3. id: '111',
    4. name: 'test',
    5. }
    6. }

    在vue子应用中,在onMounted函数中

    1. const data = (window as any).microApp.getData();
    2. console.log('getData', data)

     主应用通知子应用,根据需求采用两种不同的传入方式:

    第一种:

    1. // 主应用
    2. this.microAppService.onSendData('新的数据')
    1. // 子应用
    2. onMounted(() => {
    3. (window as any).microApp.addDataListener(e => {
    4. console.log('刷新列表页面', e)
    5. })
    6. });

    第二种:

    1. // 主应用
    2. this.microAppService.onSendData({type: '主应用通知子应用', data: '刷新列表'});
    1. // 子应用
    2. onMounted(() => {
    3. (window as any).microApp.addDataListener(e => {
    4. console.log('刷新列表页面', e)
    5. })
    6. });

    子应用给主应用发送通知,代码如下:

    1. // 子应用的触发事件
    2. // dispatch只接收对象作为参数
    3. (window as any).microApp.dispatch({ type: "子应用发送的数据"})
    1. // 主应用接收事件
    2. onHandleDataChange(e) {
    3. console.log('datachange', e.detail.data)
    4. }

    总结

            以上demo是总结的开发过程,主要陈述了以Angular为基座应用和Vue为子应用的使用方式,从依赖安装到主应用与子应用的互动,我们选择Micro-App作为实现方案,Micro-App是当下最火、讨论热度最高,使用起来最方便的技术栈。希望看到本篇博客的有缘人,可以帮助你对前端微服务的了解,欢迎在留言区留言互相讨论,共同进步。

  • 相关阅读:
    堡垒机的相关介绍
    STL 中统计计算相关算法总结
    利用CloudCompare进行点云过滤去噪(统计滤波)
    Django 项目创建第一个应用
    端口配置错误,导致RabbitMq启动报错
    大数据Hadoop之——Apache Hudi 与 Presto/Trino集成
    【Node.js项目】大事件项目:后台架构图(含具体技术栈)、典型代码
    Request
    JS如何判断文字是否溢出(被ellipsis)?
    Redis之持久化RDB&AOF
  • 原文地址:https://blog.csdn.net/friend_ship/article/details/126687066