@icebreakers/monorepo 1.2.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/assets/.husky/commit-msg +4 -1
- package/assets/.husky/pre-commit +4 -1
- package/assets/monorepo.config.ts +22 -0
- package/assets/package.json +8 -8
- package/assets/turbo.json +10 -2
- package/dist/{chunk-4NCVGJER.js → chunk-JJQVR3B4.js} +573 -364
- package/dist/cli.cjs +603 -397
- package/dist/cli.js +12 -7
- package/dist/index.cjs +622 -382
- package/dist/index.d.cts +275 -14
- package/dist/index.d.ts +275 -14
- package/dist/index.js +31 -3
- package/package.json +3 -2
- package/templates/apps/client/package.json +11 -9
- package/templates/apps/client/wrangler.jsonc +1 -1
- package/templates/apps/server/package.json +2 -2
- package/templates/apps/website/index.md +83 -121
- package/templates/apps/website/monorepo/index.md +34 -56
- package/templates/apps/website/monorepo/manage.md +102 -37
- package/templates/apps/website/monorepo/publish.md +57 -109
- package/templates/apps/website/package.json +3 -1
- package/templates/packages/vue-lib-template/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,34 +1,62 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GitClient,
|
|
3
|
+
assetsDir,
|
|
3
4
|
cleanProjects,
|
|
5
|
+
createContext,
|
|
4
6
|
createNewProject,
|
|
7
|
+
defineMonorepoConfig,
|
|
5
8
|
escapeStringRegexp,
|
|
9
|
+
getCreateChoices,
|
|
6
10
|
getFileHash,
|
|
11
|
+
getTemplateMap,
|
|
7
12
|
getWorkspaceData,
|
|
8
13
|
getWorkspacePackages,
|
|
9
14
|
init,
|
|
10
15
|
init_esm_shims,
|
|
11
16
|
isFileChanged,
|
|
12
17
|
isMatch,
|
|
18
|
+
loadMonorepoConfig,
|
|
19
|
+
logger,
|
|
20
|
+
name,
|
|
21
|
+
packageDir,
|
|
22
|
+
resolveCommandConfig,
|
|
23
|
+
rootDir,
|
|
13
24
|
setVscodeBinaryMirror,
|
|
14
25
|
syncNpmMirror,
|
|
15
|
-
|
|
16
|
-
|
|
26
|
+
templateMap,
|
|
27
|
+
templatesDir,
|
|
28
|
+
upgradeMonorepo,
|
|
29
|
+
version
|
|
30
|
+
} from "./chunk-JJQVR3B4.js";
|
|
17
31
|
|
|
18
32
|
// src/index.ts
|
|
19
33
|
init_esm_shims();
|
|
20
34
|
export {
|
|
21
35
|
GitClient,
|
|
36
|
+
assetsDir,
|
|
22
37
|
cleanProjects,
|
|
38
|
+
createContext,
|
|
23
39
|
createNewProject,
|
|
40
|
+
defineMonorepoConfig,
|
|
24
41
|
escapeStringRegexp,
|
|
42
|
+
getCreateChoices,
|
|
25
43
|
getFileHash,
|
|
44
|
+
getTemplateMap,
|
|
26
45
|
getWorkspaceData,
|
|
27
46
|
getWorkspacePackages,
|
|
28
47
|
init,
|
|
29
48
|
isFileChanged,
|
|
30
49
|
isMatch,
|
|
50
|
+
loadMonorepoConfig,
|
|
51
|
+
logger,
|
|
52
|
+
name,
|
|
53
|
+
packageDir,
|
|
54
|
+
resolveCommandConfig,
|
|
55
|
+
rootDir,
|
|
31
56
|
setVscodeBinaryMirror,
|
|
32
57
|
syncNpmMirror,
|
|
33
|
-
|
|
58
|
+
templateMap,
|
|
59
|
+
templatesDir,
|
|
60
|
+
upgradeMonorepo,
|
|
61
|
+
version
|
|
34
62
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@icebreakers/monorepo",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"description": "The icebreaker's monorepo manager",
|
|
6
6
|
"author": "ice breaker <1324318532@qq.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -42,8 +42,9 @@
|
|
|
42
42
|
"@pnpm/logger": "^1001.0.0",
|
|
43
43
|
"@pnpm/types": "^1000.8.0",
|
|
44
44
|
"@pnpm/worker": "^1000.1.13",
|
|
45
|
-
"@pnpm/workspace.find-packages": "^1000.0.
|
|
45
|
+
"@pnpm/workspace.find-packages": "^1000.0.38",
|
|
46
46
|
"@pnpm/workspace.read-manifest": "^1000.2.4",
|
|
47
|
+
"c12": "^3.3.0",
|
|
47
48
|
"commander": "^14.0.1",
|
|
48
49
|
"comment-json": "^4.2.5",
|
|
49
50
|
"consola": "^3.4.2",
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "vite",
|
|
8
8
|
"build": "vue-tsc -b && vite build",
|
|
9
|
+
"lint": "eslint .",
|
|
10
|
+
"lint:fix": "eslint . --fix",
|
|
9
11
|
"preview": "vite preview",
|
|
10
12
|
"deploy": "wrangler deploy",
|
|
11
13
|
"cf-typegen": "wrangler types",
|
|
@@ -13,21 +15,21 @@
|
|
|
13
15
|
},
|
|
14
16
|
"dependencies": {
|
|
15
17
|
"@faker-js/faker": "^10.0.0",
|
|
16
|
-
"@tanstack/vue-query": "^5.
|
|
18
|
+
"@tanstack/vue-query": "^5.90.2",
|
|
17
19
|
"@tanstack/vue-table": "^8.21.3",
|
|
18
20
|
"@tanstack/vue-virtual": "^3.13.12",
|
|
19
|
-
"@trpc/client": "^11.
|
|
21
|
+
"@trpc/client": "^11.6.0",
|
|
20
22
|
"pinia": "^3.0.3",
|
|
21
|
-
"vue": "^3.5.
|
|
23
|
+
"vue": "^3.5.22",
|
|
22
24
|
"vue-i18n": "^11.1.12",
|
|
23
25
|
"vue-router": "^4.5.1"
|
|
24
26
|
},
|
|
25
27
|
"devDependencies": {
|
|
26
|
-
"@cloudflare/vite-plugin": "^1.13.
|
|
27
|
-
"@hono/node-server": "^1.19.
|
|
28
|
+
"@cloudflare/vite-plugin": "^1.13.7",
|
|
29
|
+
"@hono/node-server": "^1.19.4",
|
|
28
30
|
"@hono/trpc-server": "^0.4.0",
|
|
29
31
|
"@tailwindcss/vite": "^4.1.13",
|
|
30
|
-
"@trpc/server": "^11.
|
|
32
|
+
"@trpc/server": "^11.6.0",
|
|
31
33
|
"@vitejs/plugin-vue": "^6.0.1",
|
|
32
34
|
"@vitejs/plugin-vue-jsx": "^5.1.1",
|
|
33
35
|
"@vue/tsconfig": "^0.8.1",
|
|
@@ -35,11 +37,11 @@
|
|
|
35
37
|
"tailwindcss": "^4.1.13",
|
|
36
38
|
"typescript": "~5.9.2",
|
|
37
39
|
"unplugin-vue-router": "^0.15.0",
|
|
38
|
-
"vite": "^7.1.
|
|
40
|
+
"vite": "^7.1.7",
|
|
39
41
|
"vite-plugin-vue-devtools": "^8.0.2",
|
|
40
42
|
"vite-tsconfig-paths": "^5.1.4",
|
|
41
|
-
"vue-tsc": "3.0.
|
|
42
|
-
"wrangler": "^4.
|
|
43
|
+
"vue-tsc": "3.0.8",
|
|
44
|
+
"wrangler": "^4.40.2",
|
|
43
45
|
"zod": "^4.1.11"
|
|
44
46
|
}
|
|
45
47
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./node_modules/wrangler/config-schema.json",
|
|
3
3
|
"name": "monorepo-client",
|
|
4
|
-
"compatibility_date": "2025-09-
|
|
4
|
+
"compatibility_date": "2025-09-17",
|
|
5
5
|
"main": "./worker/fetch-entry.ts",
|
|
6
6
|
"assets": {
|
|
7
7
|
"not_found_handling": "single-page-application"
|
|
@@ -4,148 +4,110 @@ layout: doc
|
|
|
4
4
|
|
|
5
5
|
# icebreaker's monorepo 模板
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
整套模板围绕 **pnpm + Turborepo + TypeScript** 打造,帮助团队快速落地一个可维护、可编排、可持续迭代的 `monorepo` 工程。这里我们把使用方式拆成几个核心模块,方便你按需查阅。
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
- `
|
|
15
|
-
- `
|
|
16
|
-
- 配置文件同步升级 `npx @icebreakers/monorepo@latest`
|
|
9
|
+
## 核心能力
|
|
10
|
+
|
|
11
|
+
- **工作区管理**:`pnpm` workspace + Turborepo 任务编排,内置缓存和过滤能力。
|
|
12
|
+
- **全链路 TypeScript**:所有模板(应用、类库、CLI)均使用 TS,并自带基础测试脚手架(`vitest`)。
|
|
13
|
+
- **质量与规范**:集成 `eslint`、`stylelint`、`husky`、`commitlint`、`lint-staged`,开箱即用。
|
|
14
|
+
- **自动化发布**:`changesets` + GitHub Actions + Dockerfile 模板,实现语义化发版和部署。
|
|
15
|
+
- **命令行助手**:`@icebreakers/monorepo` CLI 提供创建、同步、升级、镜像等常用命令,可通过 `monorepo.config.ts` 自定义行为。
|
|
17
16
|
|
|
18
|
-
##
|
|
17
|
+
## 快速上手
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
1. **拉取模板**:[GitHub](https://github.com/sonofmagic/monorepo-template) 右上角 `Use this template`,或克隆源码。
|
|
20
|
+
2. **安装依赖**:在 `pnpm-workspace.yaml` 所在目录执行 `pnpm install`(需要 Node.js ≥ 20,推荐 `npm i -g pnpm`)。
|
|
21
|
+
3. **可选清理**:运行 `pnpm script:clean` 移除演示包,仅保留最小打包模板;随后再次执行 `pnpm install` 更新 lockfile。
|
|
22
|
+
4. **初始化元数据**:`pnpm script:init` 会批量更新 `package.json`、`README.md` 等公共信息。
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
## 仓库结构速览
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
| 目录 | 描述 |
|
|
27
|
+
| --------------------------- | -------------------------------- |
|
|
28
|
+
| `apps/cli` | TypeScript 编写的 CLI 模板 |
|
|
29
|
+
| `apps/client` | Vue 3 + Vite 客户端示例 |
|
|
30
|
+
| `apps/server` | 基于 Hono 的服务端模板 |
|
|
31
|
+
| `apps/website` | VitePress 文档站(即本网站源码) |
|
|
32
|
+
| `packages/tsup-template` | 使用 `tsup` 打包的库模板 |
|
|
33
|
+
| `packages/unbuild-template` | 使用 `unbuild` 打包的库模板 |
|
|
34
|
+
| `packages/vue-lib-template` | Vue 组件库模板 |
|
|
35
|
+
| `packages/monorepo` | CLI 及配置同步工具,支持独立升级 |
|
|
25
36
|
|
|
26
|
-
|
|
37
|
+
## 常用脚本
|
|
27
38
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
39
|
+
| 命令 | 说明 |
|
|
40
|
+
| -------------------- | --------------------------------------------------- |
|
|
41
|
+
| `pnpm script:clean` | 清理演示仓库,保留最小模板 |
|
|
42
|
+
| `pnpm script:init` | 同步初始化 `package.json`、`README.md` 等基础信息 |
|
|
43
|
+
| `pnpm script:sync` | 使用 `cnpm` 同步所有包到 npmmirror(需预装 `cnpm`) |
|
|
44
|
+
| `pnpm script:mirror` | 为 VS Code 终端写入国内镜像环境变量 |
|
|
31
45
|
|
|
32
|
-
|
|
46
|
+
更多脚本可在根目录 `package.json` 中查看,命令介绍详见 [工具区](./tools/turborepo.md)。
|
|
33
47
|
|
|
34
|
-
|
|
48
|
+
## CLI 命令概览
|
|
35
49
|
|
|
36
|
-
|
|
50
|
+
```bash
|
|
51
|
+
npx monorepo new # 创建子包/应用
|
|
52
|
+
npx monorepo clean # 批量删除已勾选的子项目
|
|
53
|
+
npx monorepo sync # 同步所有包到 npmmirror
|
|
54
|
+
npx monorepo mirror # 写入 VS Code 镜像配置
|
|
55
|
+
npx monorepo up # 从最新模板同步配置文件
|
|
56
|
+
```
|
|
37
57
|
|
|
38
|
-
`
|
|
58
|
+
所有命令都支持在 `monorepo.config.ts` 中覆写默认行为,例如新增模板、修改同步命令、跳过 README 初始化等。配置示例见下文和 [配置中心说明](./monorepo/manage.md#使用-monorepo-configts-定制命令行为)。
|
|
39
59
|
|
|
40
|
-
|
|
60
|
+
## 自定义配置:`monorepo.config.ts`
|
|
41
61
|
|
|
42
|
-
|
|
62
|
+
```ts
|
|
63
|
+
import { defineMonorepoConfig } from '@icebreakers/monorepo'
|
|
43
64
|
|
|
44
|
-
|
|
65
|
+
export default defineMonorepoConfig({
|
|
66
|
+
commands: {
|
|
67
|
+
create: {
|
|
68
|
+
defaultTemplate: 'cli',
|
|
69
|
+
renameJson: true,
|
|
70
|
+
},
|
|
71
|
+
clean: {
|
|
72
|
+
autoConfirm: true,
|
|
73
|
+
ignorePackages: ['docs'],
|
|
74
|
+
},
|
|
75
|
+
upgrade: {
|
|
76
|
+
skipOverwrite: true,
|
|
77
|
+
targets: ['.github', 'monorepo.config.ts'],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
})
|
|
81
|
+
```
|
|
45
82
|
|
|
46
|
-
|
|
83
|
+
更多可配置项详见 [管理指南](./monorepo/manage.md)。
|
|
47
84
|
|
|
48
|
-
|
|
85
|
+
## 依赖与版本升级
|
|
49
86
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
- `@icebreakers/vue-lib-template` - [`vue3`](https://vuejs.org/) 组件库模板,使用 `vite` 打包
|
|
87
|
+
```bash
|
|
88
|
+
pnpm up -rLi
|
|
89
|
+
```
|
|
54
90
|
|
|
55
|
-
|
|
91
|
+
- `-r`:递归遍历所有 workspace
|
|
92
|
+
- `-L`:升级到最新版本
|
|
93
|
+
- `-i`:交互式选择(推荐查看差异后再确认)
|
|
56
94
|
|
|
57
|
-
|
|
58
|
-
- `@icebreakers/website` - 文档网站模板,使用 `vitepress` 搭建,也是 [monorepo.icebreaker.top](https://monorepo.icebreaker.top/) 的源代码
|
|
59
|
-
- `@icebreakers/server` - 使用 `hono` 搭建的服务端模板,使用 `typescript` 编写
|
|
60
|
-
- `@icebreakers/client` - `vue` 客户端模板
|
|
95
|
+
## 自动化发布
|
|
61
96
|
|
|
62
|
-
|
|
97
|
+
模板默认集成 [`changesets`](https://github.com/changesets/changesets) 与推荐的 GitHub Actions 工作流:
|
|
63
98
|
|
|
64
|
-
|
|
99
|
+
1. 安装 [changeset-bot](https://github.com/apps/changeset-bot)。
|
|
100
|
+
2. 在仓库设置中开启 `Actions` 的 `Read and write permissions` 并勾选允许创建 PR。
|
|
101
|
+
3. 在 `Repository secrets` 中配置 `NPM_TOKEN`(若需要 Codecov 也可配置 `CODECOV_TOKEN`)。
|
|
102
|
+
4. 运行 `pnpm changeset`、`pnpm changeset version`、`pnpm changeset publish` 完成发布;或交由 CI 自动执行。
|
|
65
103
|
|
|
66
|
-
|
|
67
|
-
- `-L` : `latest` 更新到最新
|
|
68
|
-
- `-i` : `interactive` 交互式
|
|
104
|
+
具体操作指南参见 [发包流程](./monorepo/publish.md)。
|
|
69
105
|
|
|
70
|
-
##
|
|
106
|
+
## 更多资源
|
|
71
107
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
1. 首先你需要安装 `Github App`: [changeset-bot](https://github.com/apps/changeset-bot)
|
|
79
|
-
|
|
80
|
-
2. 然后,来到你复制这个模板仓库(`repo`), 上方里的 `Settings` Tab 页面,进行 2 个操作:
|
|
81
|
-
|
|
82
|
-
### 1. 在 Github 进行 PR 和发包
|
|
83
|
-
|
|
84
|
-
选择 `Code and automation` > `Actions` > `General`
|
|
85
|
-
|
|
86
|
-
然后在右侧 `Workflow permissions` 下方选择: `Read and write permissions`
|
|
87
|
-
|
|
88
|
-
然后选中 `Allow GitHub Actions to create and approve pull requests`
|
|
89
|
-
|
|
90
|
-
最后,点击下方的保存按钮即可。
|
|
91
|
-
|
|
92
|
-
这样 `changeset` 就有权限对你进行 `PR` 和代码版本更新了!
|
|
93
|
-
|
|
94
|
-
### 2. 在 npm 发包
|
|
95
|
-
|
|
96
|
-
选择 `Security` > `Secrets and variables` > `Actions`
|
|
97
|
-
|
|
98
|
-
然后在右侧的 `Repository secrets` 设置你的 `NPM_TOKEN` 这个可以在你的 `npmjs.com` 账号中生成获取
|
|
99
|
-
|
|
100
|
-
(假如你需要单元测试代码覆盖率,你需要设置 `CODECOV_TOKEN`)
|
|
101
|
-
|
|
102
|
-
## eslint + stylelint 校验
|
|
103
|
-
|
|
104
|
-
引用到的规则参考 `https://eslint.icebreaker.top/`
|
|
105
|
-
|
|
106
|
-
[Github 地址](https://github.com/sonofmagic/eslint-config)
|
|
107
|
-
|
|
108
|
-
## 内置脚本
|
|
109
|
-
|
|
110
|
-
- `pnpm script:clean` 删去大部分的初始`repo`,只保留一个 `@icebreakers/bar` 项目作为发包打包模板
|
|
111
|
-
- `pnpm script:init` 初始化一些 `package.json` 里的字段
|
|
112
|
-
- `pnpm script:sync` 使用 `cnpm sync` 功能,把本地所有的包,同步到 [`npmmirror`](https://www.npmmirror.com/) 上,需要安装 `cnpm`
|
|
113
|
-
- `pnpm script:mirror` 使用 `cnpm` binary mirror 功能,使用国内二进制下载地址 (使用 vscode 环境变量)
|
|
114
|
-
|
|
115
|
-
## 创建新的项目
|
|
116
|
-
|
|
117
|
-
在 `monorepo` 的任意位置,打开命令行,然后执行 `npx monorepo new` 即可进入交互模式创建一个空的类库,
|
|
118
|
-
|
|
119
|
-
可通过传入 **可选**参数 `path` 进行修改, 比如 `npx monorepo new [path]`, 此时的目录就从 `foo` 变为了 `[path]`
|
|
120
|
-
|
|
121
|
-
> 命令 `new` 的别名为 `create`, 也可以使用 `npx monorepo create` 来创建新的项目
|
|
122
|
-
|
|
123
|
-
## 配置同步方式
|
|
124
|
-
|
|
125
|
-
更新 `@icebreakers/monorepo` 到最新版本,然后
|
|
126
|
-
|
|
127
|
-
在根目录下执行: `npx monorepo up`
|
|
128
|
-
|
|
129
|
-
> 假如你想直接从远端获取,可以 `npx @icebreakers/monorepo@latest up`
|
|
130
|
-
|
|
131
|
-
这个命令会把所有的文件从最新版本,对你本地进行覆盖,你可以从 `git` 暂存区把你不想要的文件剔除
|
|
132
|
-
|
|
133
|
-
### 参数
|
|
134
|
-
|
|
135
|
-
`npx monorepo up --raw`
|
|
136
|
-
|
|
137
|
-
这个命令会从全部文件中去除 `Github` 相关的文件
|
|
138
|
-
|
|
139
|
-
`npx monorepo up -i`
|
|
140
|
-
|
|
141
|
-
这个命令会进行命令行选择模式,你可以在这里对想要复制的文件进行筛选
|
|
142
|
-
|
|
143
|
-
`npx monorepo up -s`
|
|
144
|
-
|
|
145
|
-
跳过文件的新增,只保留文件的修改
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
当然你可以同时使用这多个命令
|
|
150
|
-
|
|
151
|
-
`npx monorepo up -i --raw`
|
|
108
|
+
- [为什么选择 monorepo?](./monorepo/index.md)
|
|
109
|
+
- [pnpm workspaces 与 Turborepo 组合的优势](./monorepo/manage.md)
|
|
110
|
+
- [工具链介绍](./tools/turborepo.md)
|
|
111
|
+
- [常见思考与 FAQ](./thinking.md)
|
|
112
|
+
|
|
113
|
+
> 欢迎结合自己的业务场景对模板做进一步裁剪与扩展,建议在自定义后保留 `monorepo.config.ts` 以便集中管理命令默认值。
|
|
@@ -1,68 +1,46 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 为什么选择 Monorepo?
|
|
2
2
|
|
|
3
|
-
Node.js
|
|
3
|
+
随着项目复杂度提升,Node.js 团队越来越倾向于把多套服务、组件库、CLI 工具放在同一个仓库里。Monorepo 的核心价值在于 **集中管理依赖与流程**,从而让重构、协作、发布都更高效。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Monorepo 的主要收益
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
| 维度 | 收益 |
|
|
8
|
+
| -------- | ------------------------------------------------------------------ |
|
|
9
|
+
| 依赖管理 | `pnpm` 等工具会共享缓存、避免重复安装;严格依赖隔离杜绝“幽灵依赖” |
|
|
10
|
+
| 构建效率 | 借助 Turborepo 的缓存与依赖图,仅构建真正改动的包,CI 时间显著降低 |
|
|
11
|
+
| 原子提交 | 一个提交即可跨多个模块同步改动,便于回滚与审计 |
|
|
12
|
+
| 协作体验 | 同一仓库统一配置、脚本与规范,减少跨项目跳转和环境差异 |
|
|
13
|
+
| 可复用性 | 公共库、UI 组件、工具函数在 workspace 内即可本地引用并共享 |
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
## 与 Polyrepo 的对比
|
|
10
16
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
| Polyrepo 常见痛点 | Monorepo 的解决方式 |
|
|
18
|
+
| -------------------------------- | -------------------------------------------------- |
|
|
19
|
+
| 每个仓库单独装依赖、重复维护脚本 | Workspace 共享依赖与脚本,一次配置多处使用 |
|
|
20
|
+
| 同步多个仓库中的接口或配置 | 原子提交 + Turborepo 构建,修改一次即可全仓库生效 |
|
|
21
|
+
| CI/CD 配置分散、发布流程冗长 | 基于 changesets 和统一仓库配置快速搭建自动化流水线 |
|
|
22
|
+
| 大规模重构成本高 | 搜索范围集中,易于批量修改、验证与回滚 |
|
|
14
23
|
|
|
15
|
-
|
|
24
|
+
## 常见落地场景
|
|
16
25
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
| **原子性提交** | 一个提交可以跨多个模块进行变更,方便追踪问题 |
|
|
22
|
-
| **简化跨模块协作** | 不需要在不同仓库之间切换和发布,仅通过本地引用即可调试 |
|
|
26
|
+
- **多端同仓**:Web、Server、CLI 共存,代码共享严格受控。
|
|
27
|
+
- **组件库/工具链**:公共 API 与内部应用一起维护,避免版本漂移。
|
|
28
|
+
- **微服务集成**:多个服务共享协议、类型定义,发布与部署流程统一。
|
|
29
|
+
- **巨石拆分**:将原有大型项目拆成多个 package,逐步抽象并复用。
|
|
23
30
|
|
|
24
|
-
##
|
|
31
|
+
## 迁移建议
|
|
25
32
|
|
|
26
|
-
|
|
33
|
+
1. **先集中依赖**:把最常见的公共依赖和脚本统一到根目录,利用 `pnpm workspace` 管理版本。
|
|
34
|
+
2. **逐步迁移模块**:按照业务领域或团队边界迁移子模块,保留原 CI 作为兜底。
|
|
35
|
+
3. **引入构建缓存**:配置 Turborepo,使用 `turbo run <task> --filter=<scope>` 控制任务范围。
|
|
36
|
+
4. **接入 changesets**:在迁移过程中就开始记录版本与变更,养成可发布的节奏。
|
|
37
|
+
5. **通过 monorepo.config.ts 定制命令**:按团队习惯调整 `create` 模板、`clean` 行为、`upgrade` 目标等,提高可维护性。
|
|
27
38
|
|
|
28
|
-
|
|
29
|
-
- **PNPM workspaces** / **Yarn workspaces** / **NPM workspaces**:简化依赖和 workspace 管理
|
|
30
|
-
- **ESBuild、Vite、Babel** 等构建工具对 Monorepo 的支持逐渐增强
|
|
39
|
+
## 进一步阅读
|
|
31
40
|
|
|
32
|
-
|
|
41
|
+
- [仓库管理实践](./manage.md) —— 如何将 pnpm + Turborepo + monorepo.config 协同使用。
|
|
42
|
+
- [发包与变更日志](./publish.md) —— 使用 changesets 管理版本、自动化发布。
|
|
43
|
+
- [工具专题](../tools/turborepo.md) —— 常用工具的配置与技巧。
|
|
44
|
+
- [常见思考](../thinking.md) —— 关于模块拆分、包结构的经验分享。
|
|
33
45
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- 易于规范代码风格和测试策略
|
|
37
|
-
- DevOps 部署流程统一(CI/CD 更易维护)
|
|
38
|
-
- 更容易进行全局重构(如重命名公共 API)
|
|
39
|
-
|
|
40
|
-
## Facebook、Google 等大厂的示范效应
|
|
41
|
-
|
|
42
|
-
大型公司(如 Google、Facebook、Uber、Airbnb)早期就在使用 Monorepo,逐渐被开源社区效仿:
|
|
43
|
-
|
|
44
|
-
- React、Angular、NestJS 等大型 Node/TS 项目都采用 Monorepo
|
|
45
|
-
- 社区也贡献了很多相关最佳实践和工具
|
|
46
|
-
|
|
47
|
-
## 相比 Polyrepo(多个仓库)的问题
|
|
48
|
-
|
|
49
|
-
| Polyrepo 问题 | 描述 |
|
|
50
|
-
| ---------------- | ------------------------------------ |
|
|
51
|
-
| 版本依赖管理复杂 | 多个仓库依赖版本不一致会导致兼容问题 |
|
|
52
|
-
| 跨项目协作成本高 | 修改一个接口需改多个仓库并同步发布 |
|
|
53
|
-
| 重复构建和发布 | 每个项目都要重复设置 CI/CD 流程 |
|
|
54
|
-
| 脚本和工具重复 | 每个仓库需要重复维护脚本、配置等 |
|
|
55
|
-
|
|
56
|
-
## 非常适合巨石项目拆分
|
|
57
|
-
|
|
58
|
-
比如一个巨石项目,里面有 `500` 个直接依赖,可以通过把它改造成一个 `monorepo` 的方式,逐步的把依赖和逻辑拆出来,让每个包保持独立的最小化的依赖。
|
|
59
|
-
|
|
60
|
-
拆分之后,这时候可能父项目最终有 `100` 个直接共享依赖,拆分出 `20` 个子包,每个包里只有 `20` 个依赖了, 这样依赖的可维护性就好很多。
|
|
61
|
-
|
|
62
|
-
同时这样也方便进行多模块共同开发,和进行单元测试。
|
|
63
|
-
|
|
64
|
-
假如做个比喻的话,这就像,你把原先拖成一块的项目,拆分成一个一个积木,然后把积木组合起来,这个项目就能跑了。而且其中的任意模块,都是可以单独替换和发包共享的。
|
|
65
|
-
|
|
66
|
-
## 总结
|
|
67
|
-
|
|
68
|
-
在项目小的时候,Polyrepo 管理简单清晰,但随着模块增多、团队扩大,**Monorepo 提供了更高效、可维护、标准化的开发体验**,这是它越来越被 Node.js 项目采用的核心原因。
|
|
46
|
+
> Monorepo 不是银弹,但在需要大量复用、自动化、跨团队协作的场景下,它能显著提升工程效率。关键是配合合适的工具与规范,让拆分后的每个模块都有清晰的职责与边界。
|