Turborepo でモノレポを整理したら、CI のビルドが劇的に速くなった話

複数パッケージを管理するモノレポに Turborepo を導入したところ、変更のないパッケージのビルドがキャッシュされ、CI の実行時間がかなり短縮されました。その設定と効果をまとめます。

🙌 結論から

Turborepo を導入すると、変更のないパッケージのビルドをキャッシュしてスキップできるようになります。

モノレポで複数パッケージを管理している場合、毎回すべてをビルドし直すのはかなり非効率です。

Turborepo に切り替えてからは変更のあったパッケージだけ再ビルドされるようになり、CI の実行時間が体感で半分以下になりました(^o^)/

特に規模が大きくなってきたモノレポで効果ありそう!✨

💡 モノレポが重くなっていた

仕事で使っているプロジェクトは、フロントエンド・API・共有ライブラリをひとつのリポジトリで管理するモノレポ構成でした。

パッケージが増えるにつれて、CI での npm run build がどんどん遅くなっていきました(´・ω・`)

しかも、UI コンポーネントを 1 行変えただけでも、API サーバーや共有 utils まで全部ビルドし直されてしまう状態…

これにちょっと悩んでてたのですが、調べてみて Turborepo を試すことにしました。

👀 Turborepo の仕組み

Turborepo はモノレポのビルドオーケストレーターで、タスクの依存関係と出力をキャッシュしてくれます。

npm install turbo

turbo.json に各タスクの設定を書くだけで動きます。

{
  "$schema": "https://turbo.build/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "test": {
      "dependsOn": ["build"]
    }
  }
}

"dependsOn": ["^build"]^ は「このパッケージが依存するパッケージのビルドが終わってから実行する」という意味です!

ビルドが成功すると、ソースファイルのハッシュと出力がキャッシュされます。

次回以降、ソースが変わっていなければそのキャッシュが使われてビルドステップ自体がスキップされます(^^)

✨ 導入して変わったこと

実際に CI に組み込んでみたところ、変更のないパッケージはキャッシュヒットして一瞬で完了するようになりました!

以前は全パッケージのビルドで 8〜10 分かかっていた CI が、変更点が少ないプッシュなら 2〜3 分で終わるようになっています。

けっこう助かる…🥰

ローカルでも効果があって、turbo build を使うと 2 回目以降は「キャッシュ済み」と表示されてほぼ即座に完了します。

ひとつ注意点があって、キャッシュは outputs に指定したディレクトリが対象になります。

outputs の指定が漏れていると、ビルド成果物がキャッシュに含まれないため、他のパッケージからの依存が正しく解決されなくなります(・_・;)

最初に設定するときは、各パッケージの distbuild を確認しながら outputs を丁寧に設定する方が安全です。

👍 まとめ

Turborepo は、モノレポのビルドキャッシュをほぼ設定ファイル一枚で実現してくれます。

パッケージ数が増えてきた、CI が遅くなってきた、というタイミングで導入するといいかも!

ローカルのビルドも速くなるので、開発体験もかなり改善されますね。

まだ素の npm workspaces だけで動かしているモノレポがあれば、ぜひ一度 Turborepo を試してみてください(^_^)