项目架构方案

项目架构之Monolithic/Multirepo/Monorepo

Monolithic

单仓单模块 架构

所有的代码都位于一个单一的仓库内,通常是在 src 目录下组织不同的模块和组件,也就是初学时接触到的项目结构。

结构

1
2
3
4
5
6
7
8
9
10
11
12
13
my-vue-app/
├── public/
├── src/
│ ├── assets/
│ ├── components/ # 所有共享的Vue组件
│ ├── views/ # 页面级别的组件
│ ├── router/ # 路由配置
│ ├── store/ # Vuex 状态管理
│ ├── utils/ # 工具函数
│ └── App.vue
│ └── main.js
├── package.json
└── vue.config.js

优势

构建一体化,由根 package.json 统一维护依赖,版本冲突少;

一次构建、一次部署,CI/CD 流程简单;

缺陷

随项目增长,代码臃肿且可维护性变差;

团队协作开发容易产生大量合并冲突;

复用性低,无法独立发布和复用共享模块到其他项目

适用

小型应用 / 个人项目 / 小团队(1-3人)

Monorepo

单仓多模块 架构

多个项目或模块会放在同一个仓库中,但各自保持独立的同时也可以共享代码和依赖

通过工具(如 Lerna、Turborepo、Nx、pnpm workspace)统一管理依赖和构建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
monorepo/
├── packages/
│ ├── ui-components/ # 共享UI组件库
│ │ ├── src/
│ │ ├── dist/
│ │ └── package.json
│ ├── webapp/ # 主要的Web应用
│ │ ├── public/
│ │ ├── src/
│ │ │ ├── assets/
│ │ │ ├── components/
│ │ │ ├── views/
│ │ │ ├── router/
│ │ │ ├── store/
│ │ │ ├── utils/
│ │ │ └── App.vue
│ │ │ └── main.js
│ │ ├── package.json
│ │ └── vue.config.js
│ ├── admin-panel/ # 后台管理系统
│ │ ├── public/
│ │ ├── src/
│ │ │ ├── assets/
│ │ │ ├── components/
│ │ │ ├── views/
│ │ │ ├── router/
│ │ │ ├── store/
│ │ │ ├── utils/
│ │ │ └── App.vue
│ │ │ └── main.js
│ │ ├── package.json
│ │ └── vue.config.js
├── lerna.json # 如果使用Lerna来管理多包
├── package.json # 根级package.json文件
└── .gitignore

优势

复用性强、公共模块可本地链接引用

workspace机制共享依赖(多个工作区配置共同引用一个根目录下的 package.json 文件)因此工具链也是统一的

缺陷

构建配置复杂,需要处理多包构建、依赖解析、缓存优化等问题

权限控制弱,所有代码都在一个仓库,难以对不同团队设置细粒度访问权限(但在公司层面有解决方案,比如字节,可以指定某个文件夹的可访问者是哪些人)

仓库体积大,随着项目的增长,所有的代码变更、提交都会被记录在同一个 Git 仓库的历史中,它的 .git 文件夹可能会变得非常庞大

工具

Lerna:最早的 Monorepo 管理工具,适合发布管理。

Turborepo:高性能构建系统,支持任务缓存与并行执行。

Nx:功能强大,支持代码生成、影响分析、任务调度。

pnpm workspace:轻量级,通过 pnpm 原生支持 workspace,搭配 turbo 效果更佳。

pnpm workspace 非常适用于 Monorepo 架构

  • 下载速度pnpm安装依赖时通常比其他包管理器更,这对于大型 Monorepo 来说尤为重要
  • 依赖管理:不同于 npm3.x+yarn1.x+ 将所有依赖扁平化放置在根目录下的做法,pnpm 的依赖存储是树状的,保持了依赖树的结构清晰度,还避免了潜在的安全风险(依赖劫持)。需要注意的是,npm 之前也是严格树形的,但由于没有做去重,导致 node_modules 目录巨大。因此有一个比较有名的图,node_modules 大于黑洞
  • 版本控制:多个包如果有重复的依赖项,通过 pnpm workspace,所有工作区(即子包)可以共享同一个 node_modules 目录下的依赖,避免了每个包单独安装相同依赖的情况,节省了磁盘空间和安装时间
  • 多包相同依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
node_modules/
├── .pnpm/
│ ├── lodash@4.17.21/
│ │ └── node_modules/
│ │ └── lodash -> 实际文件(只存一份)
│ ├── vue@3.2.0/

├── packages/
│ ├── ui-components/
│ │ ├── package.json
│ │ └── node_modules/
│ │ └── lodash -> ../../node_modules/lodash (软链接)
│ └── webapp/
│ ├── package.json
│ └── node_modules/
│ ├── lodash -> ../../node_modules/lodash (软链接)
│ └── vue -> ../../node_modules/vue

└── pnpm-workspace.yaml
  • 多包不同依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
node_modules/
├── .pnpm/
│ ├── lodash@4.0.0/
│ │ └── node_modules/
│ │ └── lodash -> 实际文件 v4.0.0
│ └── lodash@4.17.21/
│ └── node_modules/
│ └── lodash -> 实际文件 v4.17.21

├── packages/
│ ├── legacy-app/
│ │ └── node_modules/
│ │ └── lodash -> ../../../node_modules/.pnpm/lodash@4.0.0/node_modules/lodash
│ ├── modern-app/
│ │ └── node_modules/
│ │ └── lodash -> ../../../node_modules/.pnpm/lodash@4.17.21/node_modules/lodash
│ └── utility-lib/
│ └── node_modules/
│ └── lodash -> ../../../node_modules/.pnpm/lodash@4.17.21/node_modules/lodash

适用

中大型项目,多个子项目/微项目共存

需要大量共享代码的团队(组件库)

统一技术栈和工程规范的组织

开源项目

Multirepo

多仓多模块 架构

每个功能模块或服务可能会被独立放置在一个单独的 Git 仓库中

以两个 Vue 应用为例,分别代表 前端用户界面服务端渲染应用

用户界面

1
2
3
4
5
6
7
8
9
10
11
12
13
frontend-ui/
├── public/
├── src/
│ ├── assets/
│ ├── components/
│ ├── views/
│ ├── router/
│ ├── store/
│ ├── utils/
│ └── App.vue
│ └── main.js
├── package.json
└── vue.config.js

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ssr-app/
├── src/
│ ├── server/
│ ├── client/
│ ├── assets/
│ ├── components/
│ ├── views/
│ ├── router/
│ ├── store/
│ ├── utils/
│ └── entry-client.js
│ └── entry-server.js
├── package.json
└── vue.config.js

优势

高度解耦,每个仓库独立开发,部署,版本控制互不依赖

权限管理清晰,可为不同团队分配不同仓库的访问权限

技术栈灵活,每个仓库可使用不同的语言、框架、技术栈、构建工具

适合微服务架构或跨团队协作,便于项目交接或外包

缺陷

代码复用困难,共同逻辑得通过npm发布,本地调试不便,迭代周期长

依赖管理分散,每个仓库容易出现版本不一致的问题

修改一个公共库需要发布新版本,并手动更新所有依赖项目

CI/CD配置重复,每个仓库需要配置独立的流水线,维护成本高

适用

多团队独立开发,职责边界清晰

微服务架构,服务间松耦合

第三方合作或外包

对安全性和权限控制要求高的企业

架构总结

维度 Monolithic Monorepo Multirepo
复杂度 中~高
开发效率 高(初期) 高(中后期) 一般
代码复用性 低(需发布NPM)
构建部署 简单 复杂(需工具支持) 独立,但重复配置
团队协作 小团队友好 大团队/跨团队协作佳 团队间解耦好
权限控制
技术灵活性 中(可多技术栈)
适合项目规模 小型 中大型 中大型
典型代表 传统单体应用 Vue、React、Angular 微服务架构、开源生态