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

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

阅读数 554
点赞 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 等。

相关文章
技术文档
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
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空