@icebreakers/monorepo 1.2.4 → 2.0.1

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.
@@ -1,60 +1,125 @@
1
1
  # 如何管理 monorepo
2
2
 
3
- 我使用 `pnpm + turborepo` 来管理 `monorepo` 相较于传统做法(比如多个独立仓库或用 Yarn/NPM 管理 monorepo)有 **明显优势**,从性能、可维护性、协作效率到发布流程都有提升。下面是详细解释:
3
+ 本节结合模板实践,总结一套围绕 **pnpm + Turborepo + monorepo.config** 的管理方法:从依赖安装、任务调度到命令覆写,帮助团队高效协作。
4
+
5
+ ## 基础设施速览
6
+
7
+ | 能力 | 工具 | 要点 |
8
+ | -------------- | -------------------- | --------------------------------------------------------------------------- |
9
+ | Workspace 管理 | `pnpm` | 内容寻址、硬链接,安装速度快、占用小;严格依赖隔离杜绝“幽灵依赖” |
10
+ | 任务编排 | `turborepo` | 基于依赖图调度任务,支持并行与缓存,`turbo run build --filter=...` 精准执行 |
11
+ | 命令自定义 | `monorepo.config.ts` | 使用 `c12` 加载,可对 create/clean/sync/upgrade/init/mirror 覆写默认行为 |
4
12
 
5
- ## 核心优势一览
13
+ ## 日常操作流程
14
+
15
+ ### 1. 管理依赖
16
+
17
+ ```bash
18
+ # 安装/更新
19
+ pnpm install
20
+ pnpm up -rLi
6
21
 
7
- ### 1. **极快的依赖安装(pnpm 的硬链接 + 内容寻址)**
22
+ # 查看依赖图
23
+ pnpm ls --depth 2
24
+ ```
8
25
 
9
- - `pnpm` 使用内容寻址存储,多个项目间共享 node_modules 中的依赖,不重复安装。
10
- - 安装依赖速度远快于 `npm` / `yarn`,节省磁盘空间。
26
+ - `pnpm install` 自动按 workspace 复用依赖。
27
+ - `pnpm up -rLi` 交互式升级所有包,`-L` 为最新版本,`-i` 逐项确认。
11
28
 
12
- ### 2. **智能任务调度与缓存(turborepo)**
29
+ ### 2. 调度构建与测试
13
30
 
14
- - `turbo` 会缓存上一次的构建输出,**不变的包不会重复构建**,节省大量构建时间。
15
- - 类似于 Bazel、Nx 等构建系统,但配置简单,专注于 JavaScript/TypeScript 项目。
31
+ ```bash
32
+ # 全量构建 / 测试
33
+ pnpm build
34
+ pnpm test
16
35
 
17
- ### 3. **明确的依赖关系管理**
36
+ # 只构建受影响的包
37
+ pnpm build --filter={apps/client}
18
38
 
19
- - `pnpm` 强制使用严格的模块隔离,不允许“幽灵依赖”(hoist 下来的间接依赖)。
20
- - 每个包必须显式声明自己的依赖,减少运行时错误。
39
+ # 观察执行计划
40
+ pnpm exec turbo run build --dry=json | jq '.'
41
+ ```
21
42
 
22
- ### 4. **组件复用 + 原子包发布**
43
+ Turborepo 会缓存任务输出:
23
44
 
24
- - 各子包可单独开发、测试、构建,也可以发布到 NPM。
25
- - 例如一个 UI 组件库(`@my/ui`)被多个应用复用,改动只需维护一个位置。
45
+ | 构建场景 | 全量(首次) | 增量(未改动) |
46
+ | -------------- | ------------ | -------------- |
47
+ | 传统脚本 | 120s | 120s |
48
+ | Turbo 本地缓存 | 120s | **≈5s** |
49
+ | Turbo 远程缓存 | 120s | **≈2s** |
26
50
 
27
- ### 5. **团队协作更清晰**
51
+ > 建议在 CI 中启用远程缓存(Vercel/Turbo Cloud 或自建存储)进一步缩短时间。
28
52
 
29
- - 多人负责不同 app/package 时,统一 workspace 管理避免重复工作。
30
- - turbo 的 `--filter` 功能可以只运行特定 app/package 的任务,提高并行效率。
53
+ ### 3. 自定义命令行为
31
54
 
32
- ### 6. **支持渐进迁移/扩展**
55
+ 使用 `defineMonorepoConfig` 即可集中覆写:
33
56
 
34
- - 可以从一个项目开始,逐步迁移其他项目到 monorepo。
35
- - 不强制结构,灵活适配大型或微服务项目。
57
+ ```ts
58
+ import { defineMonorepoConfig } from '@icebreakers/monorepo'
36
59
 
37
- ## 示例:构建时间对比(真实项目)
60
+ export default defineMonorepoConfig({
61
+ commands: {
62
+ create: {
63
+ templatesDir: './custom-templates',
64
+ templateMap: {
65
+ 'cloud-function': 'apps/functions/cloud',
66
+ },
67
+ choices: [
68
+ { value: 'cli', name: 'CLI 模板' },
69
+ { value: 'cloud-function', name: '云函数模板' },
70
+ ],
71
+ },
72
+ sync: {
73
+ command: 'cnpm sync {name}',
74
+ concurrency: 4,
75
+ },
76
+ clean: {
77
+ autoConfirm: true,
78
+ pinnedVersion: '^2.0.0',
79
+ },
80
+ },
81
+ })
82
+ ```
38
83
 
39
- | 构建系统 | 全量构建时间 | 增量构建时间 | 备注 |
40
- | ---------------------- | ------------ | ------------ | ----------------------------------- |
41
- | 传统脚本 | 120s | 120s | 无缓存,每次都重建所有包 |
42
- | `turbo` | 120s | **5s** | 使用缓存和依赖图优化任务调度 |
43
- | `turbo + remote cache` | 120s | **2s** | 跨机器缓存(如 Vercel/Turbo Cloud) |
84
+ 常用配置项:
44
85
 
45
- ## 如果不用这套,你可能会遇到的问题
86
+ | 命令 | 可覆盖字段 | 说明 |
87
+ | --------- | ---------------------------------------------------------------------------------- | ------------------------------ |
88
+ | `create` | `templatesDir` / `templateMap` / `choices` / `defaultTemplate` | 扩展模板来源、修改提示内容 |
89
+ | `clean` | `autoConfirm` / `ignorePackages` / `includePrivate` / `pinnedVersion` | 控制交互、过滤包、锁定依赖版本 |
90
+ | `sync` | `concurrency` / `command` / `packages` | 定义同步命令与并发度 |
91
+ | `upgrade` | `targets` / `mergeTargets` / `scripts` / `skipChangesetMarkdown` / `skipOverwrite` | 改写配置同步策略 |
92
+ | `init` | `skipReadme` / `skipPkgJson` / `skipChangeset` | 按需跳过初始化步骤 |
93
+ | `mirror` | `env` | 注入镜像环境变量 |
46
94
 
47
- | 问题 | 结果 |
48
- | ---------------------- | ------------------------------------------------ |
49
- | 重复安装多个项目的依赖 | 时间长、磁盘大、CI 卡慢 |
50
- | 每次都构建整个仓库 | 效率低,修改一个 utils 都重新构建全部 |
51
- | 依赖混乱、版本冲突 | 运行时报错难调试,容易出现「在我机器上可以」问题 |
52
- | 多仓库协作不方便 | 开发者切来切去,难以同步更新和版本发布 |
95
+ 更多细节可参考 CLI 命令文档或源码中的 `commands/*`。
53
96
 
54
- ## 总结
97
+ ### 4. 依赖升级 / 配置同步
55
98
 
56
- **pnpm + turborepo 是现代 JS 项目的最佳实践之一,适用于微服务、组件库、多平台应用等复杂项目。**
99
+ ```bash
100
+ npx monorepo up # 使用本地 CLI
101
+ npx @icebreakers/monorepo@latest up # 直接使用远端 CLI
57
102
 
58
- > 如果你关注的是:**构建速度、复用率、协作效率** —— 这套方案绝对是值得投入的。
103
+ # 常用参数
104
+ # --raw 排除 GitHub 相关文件
105
+ # -i 以交互方式筛选文件
106
+ # -s 跳过新增,仅覆盖已存在文件
107
+ ```
108
+
109
+ 升级 CLI 后再执行 `up`,可以同步获得模板最新的工作流、脚手架与配置。
110
+
111
+ ## 常见问题与建议
59
112
 
60
- 当然,这只是我自己的最佳实践,你也可以尝试其他的方案
113
+ - **依赖冲突**:使用 `pnpm why <pkg>` 定位冲突来源,优先升级上游依赖或将共享依赖提升到顶层。
114
+ - **缓存命中率低**:确认是否使用了 `turbo run <task> --filter` 以及 `dependsOn` 配置是否准确,必要时开启远程缓存。
115
+ - **CI 时间长**:结合 `pnpm fetch` 预拉取依赖,配合 `turbo` 缓存,通常能把 pipeline 压缩到原来的 1/3。
116
+ - **命令行为差异**:将所有自定义行为写入 `monorepo.config.ts`,避免脚本散落多处难以维护。
117
+
118
+ ## 进一步阅读
119
+
120
+ - [为什么越来越多团队迁移到 monorepo?](./index.md)
121
+ - [changesets 发包指南](./publish.md)
122
+ - [工具篇:pnpm、Turborepo、Changesets 等](../tools/turborepo.md)
123
+ - [常见思考与实践](../thinking.md)
124
+
125
+ > 小提示:在迁移现有项目时,可以先把最常变的模块放进 monorepo,再逐步收拢其它仓库,配合 `monorepo.config.ts` 就能实现平滑衔接。
@@ -1,59 +1,42 @@
1
- # monorepo 发包生成变更日志
1
+ # monorepo 发包与变更日志
2
2
 
3
- `monorepo` 中发包和生成变更日志是一项关键的工作。推荐的现代做法是使用 [`changesets`](https://github.com/changesets/changesets) 专为 **monorepo 包发布** 设计的开源工具。
3
+ 本模板推荐使用 [`changesets`](https://github.com/changesets/changesets) 管理版本、生成 `CHANGELOG` 并发布 npm 包。它针对 monorepo 场景设计,维护活跃,易于与 CI/CD 集成。
4
4
 
5
- ## changesets 是什么?
5
+ ## 为什么选 changesets
6
6
 
7
- `changesets` 是一款用于:
7
+ | 场景 | changesets 能力 |
8
+ | ------------ | ------------------------------------------------------------- |
9
+ | 精确记录改动 | 每次变更生成独立的 changeset 文件,说明影响的包与语义版本类型 |
10
+ | 自动生成日志 | 基于 changeset 内容生成结构化的 `CHANGELOG.md` |
11
+ | 语义化版本 | 支持 `major` / `minor` / `patch`,并处理依赖联动升级 |
12
+ | 自动化发布 | 可在 CI 中自动创建版本 PR 或直接发布到 npm |
8
13
 
9
- - 记录每个变更的目的和版本影响
10
- - 自动生成变更日志(`CHANGELOG.md`)
11
- - 自动决定要发布哪些包,以及使用什么语义版本(`major` /`minor`/ `patch`)
12
- - 与 `CI/CD` 集成实现自动发布(支持 `GitHub Actions`)
14
+ ## 推荐流程
13
15
 
14
- ## 使用 changesets 的优势
16
+ > 以下命令默认在仓库根目录执行。
15
17
 
16
- | 优势 | 说明 |
17
- | --------------- | ------------------------------------------------------------- |
18
- | ✅ 精细控制 | 每次变更单独写一个 changeset 文件,明确说明影响的包和变更类型 |
19
- | 📦 支持多包 | 自动识别哪些包发生了变更,以及它们的依赖是否也需要发布 |
20
- | 🧾 自动生成日志 | 基于 changeset 文件生成结构清晰的 CHANGELOG.md |
21
- | 🔄 自动升级版本 | 遵循 Semver 规范,自动处理包之间的依赖升级 |
22
- | 🤖 CI/CD 集成 | 支持 GitHub Actions 自动创建版本 PR 并发布到 NPM |
23
-
24
- ## 如何在 monorepo 中使用 changesets(pnpm + turbo)
25
-
26
- ### 1. 安装依赖
18
+ ### 1. 初始化
27
19
 
28
20
  ```bash
29
21
  pnpm add -D @changesets/cli
30
22
  pnpm changeset init
31
23
  ```
32
24
 
33
- 会生成:
25
+ 生成 `.changeset/` 目录,用于存放配置与变更记录。
34
26
 
35
- ```bash
36
- .changeset/ # 存放每次变更的 YAML 文件
37
- └── cool-change.md
38
- ```
39
-
40
- ---
41
-
42
- ### 2. 编写 changeset
43
-
44
- 运行以下命令为一次变更创建记录:
27
+ ### 2. 记录变更
45
28
 
46
29
  ```bash
47
30
  pnpm changeset
48
31
  ```
49
32
 
50
- 交互式输入:
33
+ 按照提示:
51
34
 
52
- - 选择受影响的包(多个)
53
- - 选择版本变更类型(patch / minor / major
54
- - 输入 changelog 信息
35
+ 1. 选择受影响的包。
36
+ 2. 指定版本类型(`patch` / `minor` / `major`)。
37
+ 3. 填写 changelog 描述。
55
38
 
56
- 结果示例(`.changeset/awesome-change.md`):
39
+ 示例输出:
57
40
 
58
41
  ```md
59
42
  ---
@@ -61,45 +44,33 @@ pnpm changeset
61
44
  "@my/ui": patch
62
45
  ---
63
46
 
64
- feat: 新增时间工具;
65
- fix: 修复 UI 按钮颜色。
47
+ - feat(utils): 新增时间处理工具
48
+ - fix(ui): 修复按钮颜色
66
49
  ```
67
50
 
68
- ---
69
-
70
- ### 3. 版本号升级 + changelog 生成
71
-
72
- 在合并变更后,运行:
51
+ ### 3. 升级版本并生成 changelog
73
52
 
74
53
  ```bash
75
54
  pnpm changeset version
76
55
  ```
77
56
 
78
- 它会:
57
+ 命令会自动:
79
58
 
80
- - 更新每个包的 `package.json` 版本号
81
- - 修改依赖包引用版本
82
- - 更新每个包的 `CHANGELOG.md`
59
+ - 更新受影响包的 `package.json` 版本。
60
+ - 调整内部依赖引用。
61
+ - 为每个包写入或追加 `CHANGELOG.md`。
83
62
 
84
- ---
85
-
86
- ### 4. 发布到 NPM
63
+ ### 4. 发布到 npm
87
64
 
88
65
  ```bash
89
66
  pnpm changeset publish
90
67
  ```
91
68
 
92
- 自动:
69
+ changesets 会只发布有改动的包,并按照依赖顺序执行。
93
70
 
94
- - 发布已变更的包
95
- - 忽略未变更的包
96
- - 使用 monorepo 中正确的依赖版本
71
+ ### 5. GitHub Actions 自动化(可选)
97
72
 
98
- ---
99
-
100
- ### 5. 配合 GitHub Actions 自动发布(可选)
101
-
102
- 建议使用官方提供的 `create-release` GitHub Action:
73
+ 结合 `changesets/action` 实现自动创建发布 PR 或直接发布:
103
74
 
104
75
  ```yaml
105
76
  name: Release
@@ -110,80 +81,57 @@ on:
110
81
  - main
111
82
  workflow_dispatch:
112
83
 
113
- concurrency: ${{ github.workflow }}-${{ github.ref }}
84
+ permissions:
85
+ contents: write
86
+ pull-requests: write
87
+ issues: write
88
+ id-token: write
89
+
114
90
  env:
115
91
  HUSKY: 0
116
92
 
117
- permissions:
118
- contents: write # to create release (changesets/action)
119
- issues: write # to post issue comments (changesets/action)
120
- pull-requests: write # to create pull request (changesets/action)
121
- id-token: write # to use OpenID Connect token for provenance (changesets/action)
122
-
123
93
  jobs:
124
94
  release:
125
- name: Release
126
95
  runs-on: ubuntu-latest
127
96
  steps:
128
- - name: Checkout Repo
129
- uses: actions/checkout@v4
130
-
97
+ - uses: actions/checkout@v4
131
98
  - uses: pnpm/action-setup@v4
132
-
133
- - name: Setup Node.js environment
134
- uses: actions/setup-node@v4
99
+ - uses: actions/setup-node@v4
135
100
  with:
136
101
  node-version: 22
137
102
  cache: pnpm
138
-
139
- - name: Install Dependencies
140
- run: pnpm i
141
-
103
+ - run: pnpm install
142
104
  - name: Create Release Pull Request or Publish to npm
143
- id: changesets
144
105
  uses: changesets/action@v1
145
106
  with:
146
- # This expects you to have a script called release which does a build for your packages and calls changeset publish
147
107
  publish: pnpm publish-packages
148
108
  env:
149
109
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
150
110
  NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
151
- npm_config_registry: https://registry.npmjs.org
152
111
  ```
153
112
 
154
- ---
155
-
156
- ## 与其他方案对比(如 lerna、手动脚本)
113
+ `pnpm publish-packages` 为模板内脚本,可替换为自定义构建+发布流程。
157
114
 
158
- | 功能 | `changesets` | `lerna` | 手动脚本 |
159
- | ------------- | -------------- | ------------- | -------- |
160
- | 多包发布支持 | ✅ | ✅ | ❌ |
161
- | 自动生成日志 | ✅ | ❌/部分支持 | ❌ |
162
- | 精确控制变更 | ✅(逐条记录) | ❌ | ❌ |
163
- | 现代化支持 | ✅(活跃维护) | 停滞/社区维护 | ❌ |
164
- | 与 CI/CD 集成 | ✅ | 部分复杂 | ❌ |
115
+ ## 与其他方案对比
165
116
 
166
- ---
117
+ | 能力 / 工具 | changesets | lerna 经典模式 | 手写脚本 |
118
+ | -------------- | ---------- | -------------- | -------- |
119
+ | 支持多包 | ✅ | ✅ | ❌ |
120
+ | 自动 changelog | ✅ | 部分支持 | ❌ |
121
+ | 逐条记录变更 | ✅ | ❌ | ❌ |
122
+ | 维护活跃度 | 高 | 低 | 需自养 |
123
+ | CI/CD 集成 | 简单 | 相对繁琐 | 完全手工 |
167
124
 
168
- ## 示例场景
125
+ ## 常见问题 FAQ
169
126
 
170
- 比如你在 monorepo 中改了 `@my/utils` `@my/ui`,你可以:
171
-
172
- ```bash
173
- pnpm changeset
174
- # 然后写明:utils 为 minor,ui 为 patch
175
-
176
- pnpm changeset version
177
- # 自动升级 utils 到 1.3.0,ui 到 0.1.2,并更新 changelog
178
-
179
- pnpm changeset publish
180
- # 发布到 npm
181
- ```
127
+ - **是否可与 `monorepo.config.ts` 联动?** 配置文件主要用于 CLI 行为定制,发布流程仍由 changesets 主导,两者互不冲突。
128
+ - **为何 `CHANGELOG` 没生成?** 确认是否执行了 `pnpm changeset version` 并提交了 `.changeset` 文件。
129
+ - **如何避免发布某些包?** 在创建 changeset 时不勾选即可,或将包标记为 `private: true`。
182
130
 
183
- ## 总结
131
+ ## 相关资源
184
132
 
185
- 使用 `changesets`:
133
+ - [changesets 官方文档](https://github.com/changesets/changesets)
134
+ - [模板中的发布工作流示例](https://github.com/sonofmagic/monorepo-template/blob/main/.github/workflows/release.yml)
135
+ - [管理指南:pnpm + Turborepo + monorepo.config](./manage.md)
186
136
 
187
- - monorepo 最推荐的发包 + changelog 方案
188
- - 搭配 `pnpm + turbo` 非常自然
189
- - 支持团队协作、自动化流程、语义化版本管理
137
+ > 小提示:在 PR 合并前先执行 `pnpm changeset version` 并提交结果,可以在代码审查阶段提前暴露发布影响,避免遗漏。
@@ -17,7 +17,9 @@
17
17
  "scripts": {
18
18
  "dev": "vitepress dev",
19
19
  "build": "vitepress build",
20
- "preview": "vitepress preview"
20
+ "preview": "vitepress preview",
21
+ "lint": "eslint .",
22
+ "lint:fix": "eslint . --fix"
21
23
  },
22
24
  "devDependencies": {
23
25
  "@braintree/sanitize-url": "^7.1.1",
@@ -54,8 +54,8 @@
54
54
  "unplugin-vue-router": "^0.15.0",
55
55
  "vite": "^7.1.7",
56
56
  "vite-plugin-dts": "^4.5.4",
57
- "vue": "^3.5.21",
57
+ "vue": "^3.5.22",
58
58
  "vue-router": "^4.5.1",
59
- "vue-tsc": "^3.0.8"
59
+ "vue-tsc": "^3.1.0"
60
60
  }
61
61
  }