turborepo

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

turborepo

turborepo

方針

原则

Turborepo と pnpm ワークスペースの組み合わせに従う。パッケージマネージャーは pnpm に統一し、ロックファイルは pnpm-lock.yaml だけをコミットする。
Turborepo は更新が速く、turbo.json のキー名も変わってきている。設定の形に迷ったら記憶に頼らず下を引く。
turbo.json のタスク定義キーは v2 以降 tasks。pipeline は旧名。古い記事を写さない。
Turborepo をグローバルにインストールしない。
pnpm exec turbo
を使うか、ルートの devDependency として入れる。
遵循 Turborepo 与 pnpm 工作空间的组合方式。统一使用 pnpm 作为包管理器,锁文件只提交 pnpm-lock.yaml。
Turborepo 更新频繁,turbo.json 的键名也一直在变化。如果不确定配置形式,不要依赖记忆,应查阅以下资料。
turbo.json 的任务定义键从 v2 开始为 tasks。pipeline 是旧名称。不要照搬旧文章。
不要在全局安装 Turborepo。使用
pnpm exec turbo
,或者将其添加为根目录的 devDependency。

構成

结构

text
my-monorepo/
  pnpm-workspace.yaml
  turbo.json
  package.json
  apps/          デプロイ可能なアプリケーション
  packages/      共有ライブラリと設定
  • ワークスペース構成は pnpm-workspace.yaml で定義する。
  • apps と packages の分離を維持する。デプロイ可能なアプリを packages に置かない。共有ライブラリを apps に置かない。
  • ネストしたパッケージを作らない。
text
my-monorepo/
  pnpm-workspace.yaml
  turbo.json
  package.json
  apps/          可部署的应用程序
  packages/      共享库和配置
  • 工作空间配置通过 pnpm-workspace.yaml 定义。
  • 保持 apps 和 packages 分离。不要把可部署的应用放入 packages,也不要把共享库放入 apps。
  • 不要创建嵌套包。

パッケージ

包

  • 名前は
    @<org>/
    プレフィックスを持つスコープ付きにする。
  • 内部パッケージにはすべて
    "private": true
    を設定する。
  • 各 package.json に exports を定義する。main より exports を優先する。
  • 共有 TypeScript 設定を packages/tsconfig/ に置き、各パッケージがそれを継承する。
  • 内部依存は
    workspace:*
    プロトコルで参照する。
  • 名称使用带
    @<org>/
    前缀的 scoped 格式。
  • 所有内部包都设置
    "private": true
    。
  • 在每个 package.json 中定义 exports。优先使用 exports,而不是 main。
  • 将共享 TypeScript 配置放在 packages/tsconfig/ 中,并由各个包继承。
  • 内部依赖使用
    workspace:*
    协议引用。

責務パッケージ

职责包

次を packages 配下に必ず置く。
  • log ログ集約
  • error エラー集約
  • prompt AI プロンプト集約
  • env 環境変数集約
  • db データベース集約
利用側は
@<org>/log
などを
workspace:*
で依存に追加する。該当する責務を呼び出し側で再実装しない。
以下职责包必须放在 packages 目录下。
  • log:日志汇总
  • error:错误汇总
  • prompt:AI 提示词汇总
  • env:环境变量汇总
  • db:数据库汇总
使用方通过
workspace:*
添加
@<org>/log
等依赖。不要在调用方重新实现相应的职责。

package.json の生成と更新

package.json 的生成与更新

package.json をゼロから手書きしない。ルート、apps/、packages/ のいずれでも同じ。
sh
pnpm init                     # package.json を生成する
pnpm create <template>        # フレームワークの scaffolder を使う
依存関係の追加、更新、削除はコマンドで行う。
sh
pnpm add -D -w turbo typescript                            # ルートの devDependency
pnpm add --filter @<org>/dashboard zod                     # 特定パッケージの外部依存
pnpm add --filter @<org>/dashboard --workspace @<org>/log  # 内部依存を workspace:* で解決
pnpm update --filter @<org>/dashboard
pnpm remove --filter @<org>/dashboard zod
  • ルート以外を対象にするときは
    --filter
    でパッケージを指定する。
  • ワークスペース内部依存には
    --workspace
    を併用する。
  • dependencies、devDependencies、peerDependencies を直接編集しない。
  • コマンドで設定できないフィールド(name のスコープ化、private、exports、scripts)だけ、生成済みの package.json に最小限の編集を加える。
不要从零开始手动编写 package.json。无论操作根目录、apps/* 还是 packages/*,都遵循相同方式。
sh
pnpm init                     # package.json を生成する
pnpm create <template>        # フレームワークの scaffolder を使う
通过命令添加、更新和删除依赖。
sh
pnpm add -D -w turbo typescript                            # ルートの devDependency
pnpm add --filter @<org>/dashboard zod                     # 特定パッケージの外部依存
pnpm add --filter @<org>/dashboard --workspace @<org>/log  # 内部依存を workspace:* で解決
pnpm update --filter @<org>/dashboard
pnpm remove --filter @<org>/dashboard zod
  • 操作根目录以外的目标时,使用
    --filter
    指定包。
  • 添加工作空间内部依赖时,同时使用
    --workspace
    。
  • 不要直接编辑 dependencies、devDependencies、peerDependencies。
  • 仅对无法通过命令配置的字段,如 name 的 scoped 格式、private、exports 和 scripts,在生成的 package.json 中进行最小幅度的编辑。

手順例

操作示例

sh
undefined
sh
undefined

ルートワークスペース

ルートワークスペース

mkdir my-monorepo && cd my-monorepo pnpm init
mkdir my-monorepo && cd my-monorepo pnpm init

pnpm-workspace.yaml に apps/* と packages/* を定義する

pnpm-workspace.yaml に apps/* と packages/* を定義する

pnpm add -D -w turbo typescript
pnpm add -D -w turbo typescript

責務パッケージ

責務パッケージ

mkdir -p packages/log (cd packages/log && pnpm init)
mkdir -p packages/log (cd packages/log && pnpm init)

name を @<org>/log にし、private と exports を設定する

name を @<org>/log にし、private と exports を設定する

アプリ

アプリ

pnpm create next-app@latest apps/dashboard pnpm add --filter @<org>/dashboard --workspace @<org>/log
undefined
pnpm create next-app@latest apps/dashboard pnpm add --filter @<org>/dashboard --workspace @<org>/log
undefined

turbo.json

turbo.json

依存関係を考慮したタスクパイプラインを定義する。
json
{
  "$schema": "https://turborepo.dev/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**"]
    },
    "lint": {},
    "test": { "dependsOn": ["^build"] },
    "dev": { "cache": false, "persistent": true }
  }
}
  • ^build
    は依存パッケージのタスクを先に走らせる指定。
  • outputs を正確に書く。書き漏らすとキャッシュから復元されない。
  • dev のような常駐タスクは
    cache: false
    と
    persistent: true
    にする。
  • 環境変数がビルド結果に影響するなら env に列挙する。列挙しないと環境が違ってもキャッシュが当たる。
定义考虑依赖关系的任务流水线。
json
{
  "$schema": "https://turborepo.dev/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**"]
    },
    "lint": {},
    "test": { "dependsOn": ["^build"] },
    "dev": { "cache": false, "persistent": true }
  }
}
  • ^build
    表示先运行依赖包中的任务。
  • 准确填写 outputs。遗漏文件会导致这些文件无法从缓存中恢复。
  • 对于 dev 等常驻任务,设置
    cache: false
    和
    persistent: true
    。
  • 如果环境变量会影响构建结果,应在 env 中列出。否则即使环境不同,也可能会命中缓存。

コンパイル方針

编译策略

デフォルトは JIT(Just-in-Time)コンパイルパターンを採る。tsc で dist に出すコンパイル済みパターンへの切り替えは、明示的に要求されたときだけ行う。
默认采用 JIT(Just-in-Time)编译模式。只有在明确要求时,才切换为使用 tsc 编译到 dist 的预编译模式。

非 JavaScript プロジェクト

非 JavaScript 项目

Turborepo は JavaScript 専用ではない。Cargo、Go、Python などのプロジェクトも同じタスクグラフに載せられる。
Rust(Cargo)と Python は、独立してキャッシュしたい単位ごとに package.json を置き、その scripts から各言語のツールチェーンを呼ぶ。Turborepo はネイティブの依存グラフを解析せず、パッケージマネージャー上の関係を使う。
json
{
  "name": "@<org>/engine",
  "private": true,
  "scripts": {
    "build": "cargo build --release",
    "test": "cargo test",
    "lint": "cargo clippy -- -D warnings"
  }
}
turbo.json 側で inputs と outputs を書き、キャッシュを効かせる。
json
{
  "tasks": {
    "build": {
      "inputs": ["src/**", "Cargo.toml", "Cargo.lock"],
      "outputs": ["target/release/**"]
    }
  }
}
  • inputs を絞らないと、無関係なファイルの変更でキャッシュが外れる。
  • outputs に target 全体を指定すると成果物が巨大になる。必要なパスだけ指定する。
  • Cargo 自身のインクリメンタルキャッシュと二重になる。どちらで効かせるかを決めてから設定する。
Go は experimental なネイティブ対応がある。turbo.json で futureFlags を有効にし、go.work にモジュールを列挙する。この場合 Go パッケージ側に package.json は不要で、モジュールパスがパッケージの識別子になる。
json
{
  "futureFlags": { "experimentalGoWorkspaces": true }
}
experimental なので挙動が変わり得る。採用前に上のドキュメントで現状を確認する。
Turborepo 并非只支持 JavaScript。Cargo、Go、Python 等项目也可以加入同一个任务图。
对于 Rust(Cargo)和 Python,按照需要独立缓存的单位放置 package.json,并通过 scripts 调用相应语言的工具链。Turborepo 不会分析原生依赖图,而是使用包管理器所维护的依赖关系。
json
{
  "name": "@<org>/engine",
  "private": true,
  "scripts": {
    "build": "cargo build --release",
    "test": "cargo test",
    "lint": "cargo clippy -- -D warnings"
  }
}
在 turbo.json 中配置 inputs 和 outputs,以启用缓存。
json
{
  "tasks": {
    "build": {
      "inputs": ["src/**", "Cargo.toml", "Cargo.lock"],
      "outputs": ["target/release/**"]
    }
  }
}
  • 如果不限制 inputs,无关文件的修改也会导致缓存失效。
  • 如果在 outputs 中指定整个 target,产物体积会非常大。只指定必要的路径。
  • 这可能与 Cargo 自身的增量缓存重复。配置前应决定使用哪一种缓存机制。
Go 目前具有 experimental 的原生支持。在 turbo.json 中启用 futureFlags,并在 go.work 中列出模块。在这种情况下,Go 包一侧不需要 package.json,模块路径将作为包的标识符。
json
{
  "futureFlags": { "experimentalGoWorkspaces": true }
}
由于该功能仍为 experimental,其行为可能发生变化。采用前应查阅上述文档以确认当前状态。

確定前に確認する

完成前确认

  • pnpm 以外のロックファイル(package-lock.json、yarn.lock)が混ざっていないか。
  • デプロイ可能なアプリが packages に、共有ライブラリが apps に入っていないか。
  • 内部依存が
    workspace:*
    になっているか。
  • 各パッケージが private と exports を持ち、共有 tsconfig を継承しているか。
  • 責務パッケージを呼び出し側で再実装していないか。
  • turbo.json のキーが tasks になっているか。pipeline のまま残っていないか。
  • outputs と inputs と env が正確か。キャッシュが誤って当たる、または常に外れる状態になっていないか。
  • 依存の追加を手書きの package.json 編集で済ませていないか。
  • turbo をグローバルインストールしていないか。
  • 是否混入了 pnpm 以外的锁文件,如 package-lock.json、yarn.lock。
  • 可部署的应用是否被放入 packages,共享库是否被放入 apps。
  • 内部依赖是否使用了
    workspace:*
    。
  • 每个包是否都设置了 private 和 exports,并继承了共享 tsconfig。
  • 是否在调用方重新实现了职责包的功能。
  • turbo.json 的键是否使用 tasks,而不是仍然保留 pipeline。
  • outputs、inputs 和 env 是否准确,是否避免了缓存错误命中或始终失效。
  • 是否通过手动编辑 package.json 来添加依赖。
  • 是否在全局安装了 turbo。