🐈

フロントエンドのモノレポ化に向けて調査とライブラリの選定

2024/12/21に公開

本記事は、Lancers(ランサーズ) Advent Calendar 2024 の21日目の記事です。

はじめに

こんにちは!ランサーズでフロントエンドエンジニアをしている加固です。

今回はランサーズのフロントエンドで導入を検討しているモノレポに関して調査した内容をまとめました。

モノレポとは

アプリケーションやマイクロサービスの全コードを単一のモノリシックなリポジトリに保存するパターンです。
https://zenn.dev/burizae/articles/c811cae767965a

メリット

単一のリポジトリで管理できるため、以下のようなメリットが挙げられるかなと思います。

  • ロジックを共有できる
  • 複数のプロジェクトに影響する変更を一度に行える
  • リンター、フォーマッターなどの設定を共通化することによる一貫性のある開発体験

デメリット

逆に以下のようなデメリットが挙げられます。

  • リポジトリのサイズが大きくなる
  • 共通ロジックの変更による影響範囲が大きい
  • ライブラリの破壊的変更があった場合の対応コストが大きい

ポリレポとは

アプリケーションやサービスごとに個別のリポジトリが存在するパターンです。

メリット

独立した状態を保ったまま開発ができるため、以下のようなメリットが挙げられるかなと思います。

  • 開発スピードを高められる
  • 個々のプロジェクトに最適な技術を採用することが可能

https://kaminashi-developer.hatenablog.jp/entry/2023/05/22/goodbye-monorepo

デメリット

逆に以下のようなデメリットが挙げられます。

  • ライブラリのバージョン管理や同一ロジックの更新の際の横断的な対応コストが高い
  • リンター、フォーマッターなどの設定ファイルがプロジェクトごとに管理されている

なぜモノレポ化したいのか

ランサーズのフロントエンドは元々PHPとJQueryで作られており、現在はReact、Next.jsへ段階的にリプレイスを進めています。
簡易的ですが、以下のようなディレクトリ構成になっています。

.
├── frontend/
│   ├── react-project-a/
│   │   └── package.json
│   ├── react-project-b/
│   │   └── package.json
│   └── react-project-c/
│       └── package.json
└── next/
    ├── next-project-a/
    │   └── package.json
    └── next-project-b/
        └── package.json

同一リポジトリで管理されているのでポリレポとは違うのですが、それぞれのプロジェクトが独立している状態です。
そこで以下のような課題が出てきており、モノレポを検討しているという経緯です。

  • プロジェクトの数に比例してバージョン管理のコストが増大する
  • リンター、フォーマッターなどの設定ファイルがプロジェクトごとに管理されているため、開発体験に差異が生じている
  • 同一ロジックの関数がプロジェクトごとに定義されている

モノレポに求めること

ランサーズでは少人数でフロントエンドの開発をしているため、移行や管理コストを抑えるということが重要になります。

必須要件

  • ライブラリの共通化
  • リンター、フォーマッターなどの設定ファイルの共通化
  • 変更があったプロジェクトのみビルドできるよう最適化

希望要件

  • ルートディレクトリから移動せずにコマンドを実行
  • ロジックの共通化
  • 依存関係の可視化

Yarn workspaces

Yarn 1.0以降にデフォルトで備わっている機能で、これだけで簡易的なモノレポ環境を作ることができます。
ランサーズではYarnを使っているため、Yarn workspacesを使ってモノレポ環境を構築し、足りない機能をライブラリで補う形にしようと思っています。

できること

  • 複数のプロジェクトを1つのリポジトリで管理
  • 依存関係の共有(yarn.lock)
  • ロジックの共通化
  • 特定のモジュールをワークスペースごとに個別管理(nohoist)

できないこと

  • ビルドやテストのキャッシング(最適化)
  • 並列タスク実行の最適化
  • 依存関係グラフの生成

ライブラリの選定

モノレポのライブラリとして代表的なLerna、Nx、Turborepoの3つのライブラリから選定していこうと思います。
Yarn workspacesでできないことを補うためには、ビルドの最適化、依存関係グラフの生成の機能が必要ですが、3つのライブラリどれでも備わっているため以下観点で選定していきます。

  • 定期的にメンテナンスされていること
  • 導入コスト、学習コストが低いこと
  • 使いやすさ

それぞれのライブラリの詳しい機能はこちらからご覧ください。

以下所感です。

Lerna

  • 一時メンテナンスが止まっていたが、現在はNxの開発元であるNrwlが引き継いでいる
  • Nxを内包している
  • ビルドやテストの最適化をする場合、Nxの機能を使う

Nx

  • VSCode と WebStorm/Intellijのエディタプラグインがある
  • 他ライブラリと比較すると多機能な印象
  • プラグインが豊富
  • 独自の概念があり学習コストが高そう
  • Nextだとバージョンアップが大変という話もある
  • 大規模なサービスに向いている

Turborepo

  • Vercelが開発している
  • 同社のその他のツールとの連携が期待できる
  • 必要な設定ファイルが turbo.json のみでシンプル
  • Turborepo をやめたい場合に比較的容易に生の yarn Workspaces に戻せる
  • 依存関係グラフは無骨

トレンドの比較

https://qiita.com/john-Q/items/ef7c433a5f441ff89ffb#trends比較
こちらの記事を参考に比較をしてみました。

GitHub Star History

各GitHubリポジトリのStar数推移を確認します。

引用:GitHub Star History

  • lernaが圧倒的に多いが、2022年以降は伸びが緩やかになっている
  • Turborepoが2022年以降で急激に伸びている
  • NxはTurborepoほどではないものの、2022年以降伸びている

npm trendsでダウンロード数を比較しました。

引用:npm trends

  • Nxが2022年あたりから急激に伸びており圧倒的なダウンロード数になっている

State of JavaScript2024

※ライブラリの比較がしたいので、npm workspaces, Yarn workspaces, pnpmは無視して見る

使用率


引用:State of JavaScript2024

GitHubリポジトリのStar数、npm trendsと同様でNxが2022年あたりから伸びている。
Lernaが2022年あたりから落ちているのはメンテナンスが止まっていた影響かな?

認知度


引用:State of JavaScript2024
2023年以降で、Nxが急激に伸びている。
Turbborepoは2023年以降で下がっているけど依然高い認知度がある。

興味度


引用:State of JavaScript2024

Turborepo,Nxが高い関心を持たれてますが、Lernaはだいぶ下がってしまってますね。

まとめ

全ての要件を叶えているのがTurborepoで、最悪容易に切り離せるというのは魅力的だなと感じました。
今後、リプレイスが進んでいくことを考えるとNxもありかなと思いつつも、導入コストの高さとバージョンアップがしんどそうというのが懸念としてあるかなと思いました。
LernaはNxを内包しているということを考えると、Nxと同じようにバージョンアップの点がボトルネックになる可能性がある?
まあ結局のところ触ってみないとわからないところはあるので、実際に触りながら今後選定をしていきたいと思います。

最後まで読んでいただきありがとうございました。
Lancers では、一緒に働けるメンバーを募集しています!
https://recruit.jobcan.jp/lancers01/list/all/all

Discussion