上节我们学习微服务时创建了 2 个 Nest 项目,如果微服务多了,可能会创建更多项目。
那问题来了,如果有 10 个微服务,我们就创建 10 个 Nest 项目的 git 仓库么?
那肯定不行,太难维护了。
这时候我们就需要 monorepo 了。
这样,同一个 git 仓库中存放多个 Nest 项目,外层叫做 workspace。
这样就算是 10 个微服务项目,也能在一个 Git 仓库里管理起来。
Nest 是支持这种 monorepo 的方式的,我们来试试看:
nest new monorepo-test
创建个 nest 项目
我们添加一个 aaa 的路由:
@Get('aaa')
aaa() {
return 'aaa';
}
改下端口:
然后把它跑起来:
npm run start:dev
浏览器访问下:
没啥问题。
然后我们再添加一个 nest 项目:
nest g app app2
它删除了 src 和 test,并创建了 apps 目录:
这里的 apps/monorepo-test 就是之前的 src、test 代码:
而 apps/app2 就是新创建的 nest 项目,或者叫 nest app。
把之前的服务停掉,重新跑:
npm run start:dev
可以看到,跑的还是之前的那个 nest 项目,只不过换成了 webpack 编译。
为什么同样都是 nest start --watch,换成 monorepo 的形式之后,还是跑之前项目呢?
答案在 nest-cli.json 里:
之前 nest-cli.json 是这样的:
现在变成了这样:
projects 下保存着多个 nest 项目的信息,比如根目录、入口文件、src 目录、编译配置文件。
然后 sourceRoot 和 root 分别指向了默认项目的 src 目录和根目录。
所以跑 nest start 的时候,才会依然跑的是之前的项目。
很明显,如果想跑另一个项目,就要这样:
npm run start:dev app2
比如我在 app2 添加一个 bbb 的路由:
@Get('bbb')
bbb() {
return 'bbb';
}
浏览器访问下:
这样,app2 的服务就跑起来了。
原理也很简单,就是 nest cli 会根据 app 名字去读取对应的 tscofnig 文件:
这就是 nest 的 monorepo。
项目多了以后,难免有一些公共代码,这种公共代码怎么复用呢?
这就涉及到 nest 的另一个特性了:library。
创建一个 library:
nest g lib lib1
它会让你指定一个前缀,这里用默认的 @app。
然后会生成 libs/lib1 目录:
在 src 下生成了 module、service 并把它们导出了。
还在 tsconfig.json 的 paths 下添加了对应的别名配置:
在 nest-cli.json 里也多了这样一个 projects 配置:
我们在 LibService 添加一个 xxx 方法:
xxx() {
return 'xxx';
}
然后在 monorepo-test 的 app 里导入 Lib1Module:
在 controller 里注入 Lib1Service 并调用它的方法:
@Inject(Lib1Service)
private lib : Lib1Service;
@Get('aaa')
aaa() {
return 'aaa' + this.lib.xxx();
}
同样的方式,在 app2 里也导入并使用它:
@Inject(Lib1Service)
private lib : Lib1Service;
@Get('bbb')
bbb() {
return 'bbb' + this.lib.xxx();
}
然后分别把两个服务跑起来:
npm run start:dev
npm run start:dev app2
浏览器访问下 http://localhost:3001/aaa 和 http://localhost:3000/bbb
可以看到,引入的 library 中的模块生效了。
如果你只是改 lib 下的代码,不想跑服务时,可以单独编译 lib 代码:
npm run start:dev lib1
nest 的 monorepo 和 libray 用起来都挺简单的。
还有个问题,现在 build 之后的代码是什么样的呢?
删掉 dist,然后执行:
npm run build
产生了一个 apps/monorepo-test/main.js,因为现在换成 webpack 了:
然后执行:
npm run build app2
现在就多了 apps/app2/main.js
lib1 也是同理:
npm run build lib1
之所以 application 或者 library 都能知道输出目录在哪,是因为在 tsconfig.json 里配了:
案例代码在小册仓库
总结
微服务项目可能会有很多个项目,为了方便管理,我们会使用 monorepo 的方式。
monorepo 就是在一个 git 仓库里管理多个项目。
nest cli 支持 monorepo,只要执行 nest g app xxx 就会把项目变为 monorepo 的,在 apps 下保存多个 nest 应用。
nest-cli.json 里配置了多个 projects 的信息,以及默认的 project。
npm run start:dev 或者 npm run build 可以加上应用名来编译对应的 app。
此外,多个项目可能有公共代码,这时候可以用 nest g lib xxx 创建 library。
library 保存在 libs 目录下,和 apps 一样可以有多个。
nest 会为 libs 创建别名,可以在其他 app 或者 lib 里用别名引入。
这就是 nest 里创建 monorepo 以及通过 library 复用代码的方式,用起来还是比较简单的。