74 lines
No EOL
3.5 KiB
Markdown
74 lines
No EOL
3.5 KiB
Markdown
# Monorepo 基础设施与工具
|
||
|
||
本文档旨在提供 monorepo 基础设施的大纲,并解释我们做出相关决策的理由。
|
||
|
||
## 任务编排
|
||
|
||
我们的代码库大量使用了[基于 PNPM `--filter` 语法的并行化](https://pnpm.io/filtering)。这有助于最大限度地减少开发者等待构建等任务完成的时间。monorepo 中的每个项目(如果适用)将包含以下脚本:
|
||
|
||
```json
|
||
{
|
||
"scripts": {
|
||
"build": "pnpm --if-present --workspace-concurrency=Infinity --stream --filter=\"$npm_package_name...\" '/^build:project:.*$/'",
|
||
"build:project": "pnpm --if-present '/^build:project:.*$/'",
|
||
"lint": "pnpm --if-present '/^lint:lang:.*$/'",
|
||
"lint:fix": "pnpm --if-present '/^lint:fix:lang:.*$/'",
|
||
"watch:build": "pnpm --if-present --workspace-concurrency=Infinity --filter=\"$npm_package_name...\" --parallel '/^watch:build:project:.*$/'",
|
||
"watch:build:project": "pnpm --if-present run '/^watch:build:project:.*$/'"
|
||
}
|
||
}
|
||
```
|
||
|
||
这些脚本概述了所使用的命名方案,以便于[使用正则表达式进行任务并行化](https://pnpm.io/cli/run#running-multiple-scripts)。**为确保整个 monorepo 的一致性,不应编辑这些脚本。** 新脚本应使用上述正则表达式概述的命名方案添加,例如,`build:project:bundle` 可能是运行像 `webpack` 这样的工具的脚本。我们还利用了许多 PNPM 选项来确保良好的开发者体验:
|
||
|
||
- `--if-present`:确保如果脚本未找到,PNPM 不会报错。
|
||
- `--workspace-concurrency=Infinity`:尽可能多地并行运行任务。
|
||
- `--stream`:将所有脚本的输出放入单个流中,使输出清晰易读。
|
||
- `--filter="$npm_package_name..."`:此过滤器告诉 PNPM,我们希望针对当前项目**及其**依赖图中的所有依赖项(先处理依赖项)运行脚本。
|
||
|
||
为了进一步缩短构建时间,我们使用了两种额外的技术:
|
||
|
||
- 对于 `build` 脚本,我们提供了包含依赖项构建(`build`)和不包含依赖项构建(`build:project`)两种方式。
|
||
- 使用基于 `wireit` 的任务输出缓存(详情见下文)。
|
||
|
||
## 任务输出缓存
|
||
|
||
我们的仓库使用 [`wireit`](https://github.com/google/wireit) 来提供任务输出缓存。特别是,这允许我们缓存 `build` 脚本的输出,以避免不必要的运行。
|
||
目标是最大限度地减少开发者等待项目构建的时间。
|
||
|
||
```json
|
||
{
|
||
"scripts": {
|
||
"build": "pnpm --if-present --workspace-concurrency=Infinity --stream --filter=\"$npm_package_name...\" '/^build:project:.*$/'",
|
||
"build:project": "pnpm --if-present '/^build:project:.*$/'",
|
||
"build:project:bundle": "wireit"
|
||
},
|
||
"wireit": {
|
||
"build:project:bundle": {
|
||
"command": "webpack",
|
||
"files": [
|
||
"... - 包资源作为输入"
|
||
],
|
||
"output": [
|
||
"... - 包资源作为输出"
|
||
],
|
||
"dependencies": [
|
||
"dependencyOutputs"
|
||
]
|
||
},
|
||
"dependencyOutputs": {
|
||
"files": [
|
||
"... - 依赖资源作为输入",
|
||
"... - 由集成到 `pnpm install` 的 monorepo 工具自动更新",
|
||
"... - 详情请参阅 `.pnpmfile.cjs` 文件和 https://pnpm.io/pnpmfile"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
在上面的示例中,`build:project:bundle` 调用 `wireit`,后者根据资源状态有条件地执行 `webpack`。
|
||
对 `wireit` 的简化理解如下:
|
||
|
||
- 如果输入源发生更改或输出源尚未生成,`wireit` 将执行 `webpack` 命令并缓存输出源
|
||
- 如果输入源未更改,`wireit` 将从其缓存版本创建输出源 |