许可优化
许可优化
产品
产品
解决方案
解决方案
服务支持
服务支持
关于
关于
软件库
当前位置:服务支持 >  软件文章 >  Nx软件与Monorepo:Angular应用管理新选择

Nx软件与Monorepo:Angular应用管理新选择

阅读数 94
点赞 0
article_banner

什么是Monorepo

monorepo 是一种组织管理代码的方法,从字面上来理解就是把与一个项目关的 package、module、project等都放在一个仓库中进行管理。与之相对应的管理方式是 multirepo ,把与项目相关的业务拆分成不同的 module 或者 package 放在不同的仓库中,彼此之间独立维护。

随着一个项目的不断迭代更新,我们会根据公司复杂的业务将部分复用代码或者常用组件拆分成 module 或者 library。是将这些众多的独立的 module 放在不同的 repository 中,然后由划分了不同职责的小组来进行独立维护,还是将这些 module 放入一个 repository 中由所有人一起维护。这就就需要考虑到 monorepo 和 multirepo 各自的优缺点。在我接触公司业务之初,尝试使用过 mutirepo,当时我们使用私有的 npm 管理多个独立的业务模块,这样既保证了主项目代码的整洁程度,也在项目初期大幅度降低了代码耦合度。可是随之而来的问题是,每次独立模块的更改,都需要单独的打包、发布、编写 changelog。在人手不多的初期,这种做法增加了我们的维护成本。通过资料查阅,我知道了还有 monorepo 这种管理方式,并且随之了解到了 Nx 这款适配 Angular 框架的扩展工具,我们把所有 module 和 libaray 放在同一个 repository 下,这样我们可以使用同一套标准管理代码,独立模块中的修改能够立马展现,代码结构也能得到改善。

Angular 源码也使用 monorepo 来管理,使用 monorepo 来管理代码的还包括 (React、Babel、Google...)

关于 Nx

官网:nx.dev
Nx 是一个用来构建 monorepos 的开发工具。自己从 Angular 6.X 版本的时候开始尝试使用 Nx 管理项目代码,那时候的 Nx 还只支持对 Angular 框架的扩展,现在的 Nx 添加了对 React 框架的支持,并且可以集成使用 Cypress, Jest , Prettier , TypeScript 等现在构建工具,支持 NestJs (一款 nodejs 后端框架),完成了对整个全栈生态的覆盖。非常推荐大家上手尝试一下。

使用 Nx WorkSpace 打造 monorepos

本篇文章通过 Nx 创建一个 fullstack 项目,以最简单的 todo 为例,分别有两个 application,两个 library,通过这个简单的例子展示一下 Nx 强大的工作流,以及如何管理 monorepo,如何集成最新的构建工具的能力。

创建工作区

创建一个空的 Nx workSpace 项目非常简单,你可以使用以下命令安装

  • npx: npx create-nx-workspace@latest todoapp
  • npm: npm init nx-workspace todoapp
  • yarn: yarn create nx-workspace todoapp

如果你已经拥有了一个自己的 Angular 项目,也可以使用 ng add @nrwl/workspace 命令将原有项目,改造成 monorepos 。脚本会在保留项目原有代码的基础上,修改文件夹结构。一个通过 Nx 创建的 Angular monorepo 空项目文件结构如下图所示:

简单介绍一下几个特殊文件/文件夹:

  • apps: 之前的单一的 project 会被迁移到这个文件夹中,方便日后统一管理多个 project
  • libs: 我们抽象出来的 module 或者 library 会被统一放在这个目录下管理
  • tools: 给不同工作区配置的不同的 schematic 会被放在这个目录下
  • nx.json: 配置当前工作区的路径;配置不同项目之间的依赖关系;配置项目所属 tag ,用来管理后续不同项目之间的导入规则
  • emmm...还有一些就是 Angular 项目中常见的配置文件

创建前/后端项目

添加前端项目,通过以下命令创建:

ng generate @nrwl/angular:application frontend

这条命令会在 apps 目录下生成 fronted 和 frontend-e2e(后续用来编写 e2e 测试) 两个项目,生成的项目和 Angular Cli 生成出来的没有任何区别


添加后端项目,通过以下命令创建:

ng generate @nrwl/nest:application backend --frontendProject=frontend

这条命令会在 apps 目录下生成 backend 项目,后端项目我选择了使用 Nest,Nx 本身也对 Nest 有着很好的支持,语法更符合 Angular 程序员

接下来我们简单编写一下项目逻辑,首先是后端服务器
apps/backend/src/app/app.service.ts

import { Injectable } from '@nestjs/common';
import { Todo } from '@todoapp/data';

@Injectable()
export class AppService {

  /** 原始数据 */
  todos: Todo[] = [{ title: 'Todo1' }, { title: 'Todo2' }];

  /** 增加数据 */
  addTodo(): void {
    this.todos.push({
      title: `Random ${ Math.floor(Math.random() * 100) }`
    });
  }
}

apps/backend/src/app/app.controller.ts

import { Controller, Get, Post } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}
    /** get 方法,用来拉取初始数据 */
  @Get('todos')
  getData() {
    return this.appService.todos;
  }

  /** post 方法,用来增加数据 */
  @Post('add')
  add() {
    return this.appService.addTodo();
  }
}

编写前端
apps/frontend/src/app/app.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Todo } from '@todoapp/data';

@Component({
  selector: 'todoapp-root',
  templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
  todos: Todo[];

  constructor(private http: HttpClient) {
    this.fetch();
  }

  /** 请求数据 */
  fetch(): void {
    this.http.get('/api/todos')
      .subscribe((t: any) => {
        this.todos = t;
      });
  }

  /** 增加数据 */
  addTodo(): void {
    this.http.post('/api/add', {})
      .subscribe(() => {
        this.fetch();
      });
  }
}

apps/frontend/src/app/app.component.html

<h1>Todo2</h1>
<todoapp-task-list [todos]="todos"></todoapp-task-list>
<button id="add-todo" (click)="addTodo()">Add Todo</button>

创建 library

创建一个 data library,用来存放 frontend 和 backend 中共用的数据结构 ToDo

ng generate @nrwl/workspace:library data


libs/data/src/index.ts

export interface Todo { title: string };

创建一个 ui library,用来存放 frontend 中抽象的组件逻辑,此处我们创建一个 task-list 组件,用来显示 todo-list

ng generate @nrwl/angular:library ui
ng generate @schematics/angular:component task-list --project=ui --export

最后我们的 libs 文件夹中会是这样的结构:


这样我们的公用逻辑都被拆分到了 libs 文件夹中,可以由不同小组成员去负责和维护,降低了代码耦合度。使用这些 lib 也很简单,例如 import { Todo } from '@todoapp/data' import { UiModule } from '@todoapp/ui'

更强大的 Nx

如果只是以上这些功能,可能会觉得比较没意思,只是满足了基本的需求,现代的前端工具应该更多的是智能酷炫,方便团队之间复杂的协作。接下来我展示一些实用的功能。

约束不同 lib 之间的依赖关系

我们不希望后端团队导入前端团队编写的 UiModule 。我们可以借用 tslint 实现,nx.json 可以给不同 app 和 lib 打上特殊的 tag,tslint 会在 import 语句中检查是否在当前项目中导入了不属于自己的模块。


在 nx.json 中,我们给 UiModule 打上 "platform:frontend" 的标签,backend 打上 "platform:backend" 标签


在 tslint.json 中增加 "nx-enforce-module-boundaries" 规则,并且规定 "platform:backend" 标签下只能导入标签为 "platform:backend" 的模块。


配置完毕,重启编辑器,我们能够顺利看到 backend 项目中 module 导入 UiModule 会提示错误。

查看依赖关系图

当项目越来越庞大时,我们可能需要查看不同项目之间的依赖关系,Nx 提供数据可视化的方案,可以以下命令查看:

nx affected:dep-graph


集成 Cypress 测试

ng run frontend-e2e:e2e --watch
动图封面

强大的功能还有很多,不一一介绍了,可以上官网查阅

总结

Nx 可以用来以 monorepos 的方式构建全栈项目,比较像是 Angular Cli 的扩展,所有 Angular Cli 能做的它都能做,Nx 对 Angular 项目的兼容度很高,熟悉 Cli 命令的人能够快速上手。如果想要尝试以更加工程化的方式管理业务代码,推荐大家尝试


免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删

武汉格发信息技术有限公司,格发许可优化管理系统可以帮你评估贵公司软件许可的真实需求,再低成本合规性管理软件许可,帮助贵司提高软件投资回报率,为软件采购、使用提供科学决策依据。支持的软件有: CAD,CAE,PDM,PLM,Catia,Ugnx, AutoCAD, Pro/E, Solidworks ,Hyperworks, Protel,CAXA,OpenWorks LandMark,MATLAB,Enovia,Winchill,TeamCenter,MathCAD,Ansys, Abaqus,ls-dyna, Fluent, MSC,Bentley,License,UG,ug,catia,Dassault Systèmes,AutoDesk,Altair,autocad,PTC,SolidWorks,Ansys,Siemens PLM Software,Paradigm,Mathworks,Borland,AVEVA,ESRI,hP,Solibri,Progman,Leica,Cadence,IBM,SIMULIA,Citrix,Sybase,Schlumberger,MSC Products...

相关文章
QR Code
微信扫一扫,欢迎咨询~
customer

online

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 board-phone 155-2731-8020
close1
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空