XGitHub

モノレポ学習でTurborepoを試してみました

Published Icon
2024-11-16
Tag Icon

最小構成で作成

まずはルートディレクトリにpackage.jsonを作成し、以下のように設定します。

package.json
{
  "name": "my-turborepo",
  "private": true,
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint"
  }
}

この設定で、appspackagespackage.jsonあるディレクトリがパッケージとみなされます。

WARNING

Turborepo はpakcages/**のようなネストしたパッケージには対応していません。 ディレクトリごとにグループ化したい場合は、packages/group/*のように設定する必要があります。

次にturboをインストールします。

pnpm add turbo --save-dev --ignore-workspace-root-check

IMPORTANT

turboは開発者用ツールであり、ワークスペース全体で利用することを想定しているため、 ワークスペースのルートに追加するのが一般的ですが、pnpmはデフォルトで禁止しています。 このような場合に--ignore-workspace-root-checkを使用することで制限を無視してインストールできます。 npmを使用する場合には関係ありません。

インストール後は以下のようになっているはずです。

package.json
{
  "name": "turborepo-intro",
  "private": true,
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint"
  },
  "devDependencies": {
    "turbo": "^2.2.3"
  },
  "packageManager": "pnpm@8.15.6",
  "engines": {
    "node": ">=22"
  }
}

またlockファイルも作成されていると思いますが、これはturboでも依存関係を把握するために使用するため、もし存在しない場合は予期せぬ動作をする可能性があります。

Packages

exportsフィールドは、設定したパッケージを他のパッケージで使用する場合のエントリーポイントになります。

@repo/mathパッケージがある場合は以下のように、それぞれの計算方法ごとの関数でエクスポートできます。

./packages/math/package.json
{
  "exports": {
    ".": "./dist/constants.ts",
    "./add": "./dist/add.ts",
    "./subtract": "./dist/subtract.ts"
  }
}

TIP

package.jsonnameフィールドはワークスペース内で一意でなければならないです。 そのためパッケージ名を@organization-name/package-nameとするのがベストプラクティスです。

CAUTION

エクスポートでは以下を注意することでパフォーマンスが向上します。

  • バレルファイルを避ける
  • package.jsonmainフィールドではなく、exportsフィールドを使用する

workspace

pnpmを使ってworkspaceを設定する場合は、pnpm-workspace.yamlファイルを作成する必要があります。

pnpm-workspace.yaml
packages:
  - "apps/*"
  - "packages/*"

appspackagesはそれぞれ上記のように設定するとworkspaceの対象になります。

turbo.json

以下の内容で、package.jsonscriptsで一致するdevbuildが一つのコマンドで実行できる。

turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "ui": "tui",
  "tasks": {
    "dev": {
      "cache": false
    },
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "lint": {
      "dependsOn": ["^lint"]
    }
  }
}

imports

importsフィールドは、パッケージ内の他のモジュールへのサブパスを作成するのに使用します。

{
  "imports": {
    "#*": "./src/*"
  }
}