1-1 微服务项目monorepo改造,加入版本控制
为什么要改造为 Monorepo
随着微服务数量增加,每个服务独立仓库的管理成本会急剧上升——尤其是当多个服务共享 proto 文件时,修改一处需要同步多个仓库。将微服务项目改造为 Monorepo(单体仓库)有以下好处:
- 方便调试:所有服务在同一仓库中,启动和调试更便捷
- 共享代码:proto 文件、工具函数等可抽取为共享包
- 统一版本管理:一个 Git 仓库管理所有服务的版本
注意:实际工作中,很多微服务代码仅限于组织内部访问,对外只暴露 proto 文件或公共 package。
改造步骤
1. 创建 pnpm workspace
在所有微服务目录的上级创建 pnpm-workspace.yaml:
packages:
- 'packages/gateway'
- 'packages/user'
- 'packages/template'
- 'packages/proto-pkg'
yaml
2. 初始化项目
# 初始化根目录 package.json
npm init -y
# 初始化 Git 仓库
git init
# 添加 .gitignore(复制任一子项目的即可)
bash
3. 清理子项目的独立 Git 仓库
NestJS CLI 创建的项目自带 .git 目录,需要删除以避免子模块冲突:
# Mac/Linux
rm -rf packages/user/.git
rm -rf packages/gateway/.git
rm -rf packages/template/.git
bash
4. 配置启动脚本
在根目录 package.json 中配置各服务的启动命令:
{
"scripts": {
"dev:user": "pnpm --filter @remote/user run start:dev",
"dev:gateway": "pnpm --filter @remote/gateway run start:dev"
}
}
json
使用 pnpm --filter 指定要运行的服务名称。
5. 抽取 proto 共享包
创建 packages/proto-pkg 目录,包含:
| 文件 | 作用 |
|---|---|
proto/user.proto | Protobuf 服务定义文件 |
index.js | 读取 proto 文件并生成 package definition |
package.json | 依赖和脚本配置 |
package.json 关键配置:
{
"name": "@remote/proto-pkg",
"dependencies": {
"@grpc/grpc-js": "^1.x",
"@grpc/proto-loader": "^0.7.x"
}
}
json
6. 替换各服务中的 proto 引用
在 gateway 和 user 的 package.json 中添加共享包依赖:
{
"dependencies": {
"@remote/proto-pkg": "workspace:*"
}
}
json
在服务代码中将原先的本地 proto 加载替换为:
import { loadProto } from '@remote/proto-pkg'
// 加载 proto 文件(自动补全 .proto 后缀)
const packageDef = loadProto('user')
typescript
loadProto 函数内部会自动判断是否需要补全 .proto 后缀。
验证
依次启动各服务并发起请求,确认改造后的功能正常:
# 启动 user 微服务
pnpm dev:user
# 启动 gateway 网关
pnpm dev:gateway
bash
参考资源
- pnpm Workspace 文档 - Monorepo 配置
- NestJS Microservices - 微服务基础
↑