Monorepo初体验:将现有的NG CLI工程改造成Monorepo方式

举报
Kagol 发表于 2021/06/18 19:13:25 2021/06/18
【摘要】 DevUI 是一款面向企业中后台产品的开源前端解决方案,它倡导沉浸、灵活、至简的设计价值观,提倡设计者为真实的需求服务,为多数人的设计,拒绝哗众取宠、取悦眼球的设计。如果你正在开发 ToB 的工具类产品,DevUI 将是一个很不错的选择! 前言Monorepo 能够优雅地解决代码复用的问题,统一工作流,并且不影响构建、部署的效率。目前开源社区已经有不少开源项目都是采用 Monorepo 的方...

DevUI 是一款面向企业中后台产品的开源前端解决方案,它倡导沉浸灵活至简的设计价值观,提倡设计者为真实的需求服务,为多数人的设计,拒绝哗众取宠、取悦眼球的设计。如果你正在开发 ToB工具类产品,DevUI 将是一个很不错的选择!

Kagol.png

前言

Monorepo 能够优雅地解决代码复用的问题,统一工作流,并且不影响构建、部署的效率。

目前开源社区已经有不少开源项目都是采用 Monorepo 的方式管理源码的,比如:Vue3,以下是它的部分源码结构:



vue-next


├── CHANGELOG.md


├── LICENSE


├── README.md


├── api-extractor.json


├── jest.config.js


├── package.json


├── packages // 每一个包在一个文件夹下,独立测试、独立构建、独立部署


|  ├── compiler-core


|  ├── compiler-dom


|  ├── compiler-sfc


|  ├── compiler-ssr


|  ├── global.d.ts


|  ├── reactivity


|  ├── runtime-core


|  ├── runtime-dom


|  ├── runtime-test


|  ├── server-renderer


|  ├── shared


|  ├── size-check


|  ├── template-explorer


|  └── vue


|     ├── README.md


|     ├── __tests__


|     ├── api-extractor.json


|     ├── examples


|     ├── index.js


|     ├── package.json


|     └── src


├── rollup.config.js


├── ...


我们一起来看看如何将一个现有的NG CLI工程切换成Monorepo,并在Monorepo的工作空间里不断扩展新项目吧!

创建一个 NG CLI 项目

我们先来创建一个CLI工程,并将其启动起来。



ng n my-portal --style=scss

cd my-portal

npm start


访问以下链接就能将项目启动起来:

http://localhost:4200/

初始工程.png

升级成 Monorepo

我们已经有了一个 NG CLI,将其变成 Monorepo 工作空间非常简单,只需要一个命令:



ng add @nrwl/workspace


执行该命令后,我们的项目结构发生了一些改变,以下是主要的变化:



DELETE .browserslistrc


DELETE tsconfig.app.json


DELETE tsconfig.spec.json


DELETE tsconfig.json


RENAME src/app/app-routing.module.ts => apps/my-portal/src/app/app-routing.module.ts


RENAME src/app/app.component.html => apps/my-portal/src/app/app.component.html


RENAME src/app/app.component.scss => apps/my-portal/src/app/app.component.scss


RENAME src/app/app.component.spec.ts => apps/my-portal/src/app/app.component.spec.ts


RENAME src/app/app.component.ts => apps/my-portal/src/app/app.component.ts


RENAME src/app/app.module.ts => apps/my-portal/src/app/app.module.ts


RENAME src/assets/.gitkeep => apps/my-portal/src/assets/.gitkeep


RENAME src/environments/environment.prod.ts => apps/my-portal/src/environments/environment.prod.ts


RENAME src/environments/environment.ts => apps/my-portal/src/environments/environment.ts


RENAME src/favicon.ico => apps/my-portal/src/favicon.ico


RENAME src/index.html => apps/my-portal/src/index.html


RENAME src/main.ts => apps/my-portal/src/main.ts


RENAME src/polyfills.ts => apps/my-portal/src/polyfills.ts


RENAME src/styles.scss => apps/my-portal/src/styles.scss


RENAME src/test.ts => apps/my-portal/src/test.ts


RENAME e2e/src/app.e2e-spec.ts => apps/my-portal-e2e/src/app.e2e-spec.ts


RENAME e2e/src/app.po.ts => apps/my-portal-e2e/src/app.po.ts


RENAME e2e/protractor.conf.js => apps/my-portal-e2e/protractor.conf.js


RENAME e2e/tsconfig.json => apps/my-portal-e2e/tsconfig.json


CREATE apps/my-portal/.browserslistrc (703 bytes)


CREATE apps/my-portal/tsconfig.app.json (223 bytes)


CREATE apps/my-portal/karma.conf.js (1013 bytes)


CREATE apps/my-portal/tsconfig.spec.json (268 bytes)


CREATE tools/schematics/.gitkeep (0 bytes)


CREATE tools/tsconfig.tools.json (251 bytes)


CREATE nx.json (433 bytes)


CREATE libs/.gitkeep (0 bytes)


CREATE .vscode/extensions.json (144 bytes)


CREATE .prettierrc (26 bytes)


CREATE tsconfig.base.json (416 bytes)


CREATE decorate-angular-cli.js (2628 bytes)


UPDATE karma.conf.js (1016 bytes)


UPDATE package.json (2035 bytes)


UPDATE angular.json (4659 bytes)


UPDATE tslint.json (3491 bytes)


比较明显的改变就是:

  • 将src和tsconfig的代码迁移到apps中

  • 增加了nx.json配置文件

这时我们重新执行npm start启动项目,并通过链接http://localhost:4200/访问页面。

看起来和之前没有任何的不同,不过实质已发生巨大的变化。就像变成白袍巫师的甘道夫,穿上灰袍,看着还是以前的“灰袍巫师甘道夫”,不过早已经历了蜕变。

图片.png

增加一个 Angular 项目

升级成 Monorepo 的 NG CLI 工程就像变成白袍后的甘道夫,拥有平行扩展的能力,可以增加任意的子项目,而不增加构建的成本。

比如我们想增加一个 Angular 项目,只需要执行以下命令:



npx nx g @nrwl/angular:app projectman-portal


这时apps目录下会新增一个projectman-portal目录:



├── apps


|  ├── my-portal


|  ├── projectman-portal // 新增的


新增加的子项目和之前的项目是完全独立的,不影响之前项目的本地启动、测试、构建、部署等。

启动子项目:



npx nx serve projectman-portal --port 4100


图片.png

my-portal和projectman-portal启动时,会使用不同的端口号,本地开发互不影响。

公共部分 shared

现在我们有一个主应用my-portal和一个子应用projectman-portal,如果这两个项目中有一个公共的模块:成员管理,我们要怎么实现模块复用呢?

新建公共模块

可以在apps下新建一个shared文件夹,由于是Angular项目,再建一个angular子文件夹。



├── apps


|  ├── my-portal


|  |  ├── karma.conf.js


|  |  ├── src


|  |  ├── tsconfig.app.json


|  |  └── tsconfig.spec.json


|  ├── projectman-portal


|  |  ├── jest.config.js


|  |  ├── src


|  |  ├── tsconfig.app.json


|  |  ├── tsconfig.editor.json


|  |  ├── tsconfig.json


|  |  └── tsconfig.spec.json


|  └── shared


|     └── angular


然后在angular下新建一个component文件夹,并使用 NG CLI 命令快速创建一个member模块:



cd apps/shared/angular/component

// 新建模块


ng g m member-list

// 在模块下新建组件


ng g c member-list




├── apps


|  └── shared


|     └── angular


|        └── component


|           └── member-list


|              ├── member-list.component.html


|              ├── member-list.component.scss


|              ├── member-list.component.spec.ts


|              ├── member-list.component.ts


|              └── member-list.module.ts


在业务中使用

我们在my-portal和projectman-portal两个业务中都使用menber-list组件。

导入member模块

apps/my-portal/src/app/app.module.ts

apps/projectman-portal/src/app/app.module.ts



import { MemberListModule } from '@component/member-list/member-list.module';

  imports: [


    MemberListModule,


  ],


使用member组件

apps/my-portal/src/app/app.component.html

apps/projectman-portal/src/app/app.component.html



<app-member-list></app-member-list>


由于有热加载,保存后马上就能实时看到页面效果

图片.png

图片.png

配置tsconfig

为了引入方便,我们在tsconfig中配置了@component路径别名。

tsconfig.base.json



    "paths": {


      "@shared/*": ["apps/shared/*"],


      "@component/*": ["apps/shared/angular/component/*"]


    },


这样在业务中使用公共组件,就不用写很长的../../,直接使用@component别名即可:



import { MemberListModule } from '@component/member-list/member-list.module';


增加一个 React 项目

除了Angular项目,我们还可以在 Monorepo 工作空间中增加别的框架的项目,比如:React。

增加React项目的方式和Angular类似,只是需要增加一个@nrwl/react依赖:



npm i -D @nrwl/react

npx nx g @nrwl/react:app workitem-portal


要不然会报以下错误:



Unable to resolve @nrwl/react:app.


Cannot find module '@nrwl/react/package.json'


创建完会在apps目录下新增一个workitem-portal



├── apps


|  ├── my-portal


|  ├── projectman-portal


|  ├── workitem-portal // 新增的


启动方式也是一样的:



npx nx serve workitem-portal --port 4200


我们注意到启动时报了一个错:



ERROR in /Users/kagol/Documents/Kagol/code/devcloud-portal/apps/workitem-portal/src/app/app.tsx(10,5):


TS17004: Cannot use JSX unless the '--jsx' flag is provided.


需要在workitem-portal/tsconfig.json中作相应的配置:



{


  "compileOnSave": false,


  "compilerOptions": {


    ...


    "jsx": "preserve", // "jsx": "react-jsx"


    ...


  }


}


访问链接:

http://localhost:4200/

可以看到我们的React项目也能正常启动:

图片.png

按照同样的步骤,我们可以扩展出很多子项目,它们之间共同同样的工作流,同样的公共代码,非常方便和高效,赶紧试试吧!

增加启动和构建脚本

为了方便地启动和管理多个项目,可以在package.json中增加启动和构建的脚本:



"start": "npx nx serve devcloud-portal --port 4200 --open",


"start:projectman-portal": "npx nx serve projectman-portal --port 4210",


"start:workitem-portal": "npx nx serve workitem-portal --port 4220",

"build:devcloud-portal": "npx nx build devcloud-portal --prod",


"build:projectman-portal": "npx nx build projectman-portal --prod",


"build:workitem-portal": "npx nx build workitem-portal --prod",


小结

本文先是与大家分享如何将一个现有的Angular CLI工程“变成”Monorepo工作空间,然后对其进行扩展,比如增加Angular项目、增加React项目,增加公共模块等,有了Monorepo,我们就可以将自己组织的所有项目代码统一到一个仓库里,共享同一套工作流,同一套规范,同一套公共基础库,大大地提升了团队协作和开发的效率。

如果觉得好用,不妨在你的组织尝试下吧!

欢迎加DevUI小助手微信:devui-official,一起讨论Angular技术和前端技术。

欢迎关注我们DevUI组件库,点亮我们的小星星🌟:

https://github.com/devcloudfe/ng-devui

也欢迎使用DevUI新发布的DevUI Admin系统,开箱即用,10分钟搭建一个美观大气的后台管理系统!

加入我们

我们是DevUI团队,欢迎来这里和我们一起打造优雅高效的人机设计/研发体系。招聘邮箱:muyang2@huawei.com。

文/DevUI Kagol

往期文章推荐

《Angular路由:懒加载、守卫、动态参数》

《今天是儿童节,整个贪吃蛇到编辑器里玩儿吧》

《如何将龙插入到编辑器中?》

《Quill富文本编辑器的实践》

《号外号外!DevUI Admin V1.0 发布啦!》

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。