moon が v2.0 に到達。コードネームは Phobosmoon exec を軸に moon ci / moon check / moon run を統一Moonrepoの moon は、ひとことで言うと モノレポ管理のための道具箱 です。
モノレポというのは、複数のアプリやライブラリを1つのリポジトリでまとめて管理するやり方のこと。規模が大きくなるほど「どのプロジェクトで何をどう実行するか」を揃えるのが面倒になり、そこで登場するのがこういうツールです。
今回の Moon v2.0 で一番の目玉は、toolchain の仕組みが大きく変わったことです。
toolchain はざっくり言えば「そのプロジェクトが使う言語や実行環境、ビルド周りの道具立て」のこと。これまで moon では、この部分がコアに組み込まれていました。つまり、対応言語は開発元が実装したものにかなり依存していたわけです。
そこを v2.0 では、WASMベースのプラグイン方式に切り替えました。
WASM は WebAssembly の略で、ブラウザだけでなく「軽くて安全に動く実行形式」としていろいろな場面で使われています。ここでは、外部のプラグインを柔軟に動かすための土台として使われています。
これの何がうれしいかというと、コミュニティが独自の toolchain プラグインを作れるようになることです。
対応言語やランタイムを moon の中に閉じ込めず、必要ならユーザー側で拡張できる。これはかなり大きいです。正直、モノレポ系ツールの弱点って「便利だけど、対応範囲が狭いと一気に窮屈になる」ことなので、ここをプラグイン化したのはかなり筋がいいと思います。
v2.0 では、設定ファイルの形式がかなり増えました。
対応したのは JSON、JSONC、HCL、Pkl、TOML。従来の YAML にももちろん対応しています。
これは一般の人には「ファイル形式が増えただけ?」と思えるかもしれませんが、実務では結構効きます。
チームによっては YAML が読みづらいと感じる人もいれば、逆に JSON 系のほうが機械的で扱いやすいこともあります。TOML は設定ファイルとして見やすいですし、HCL はTerraform系の文脈で馴染みがある人も多いでしょう。
つまり moon は、1つの正解を押しつけるより、現場の好みに寄せられる方向に進んだわけです。こういう「柔らかさ」は、採用しやすさに直結します。
CLI もかなり作り直されています。
中心になるのは新しい低レベルコマンドの moon exec で、これが moon ci、moon check、moon run の土台になります。
簡単に言うと、バラバラだった実行の入口を一段まとめた感じです。
これにより、ジョブの並列実行や、影響のある範囲だけを絞って実行する機能が扱いやすくなっています。モノレポでは「全部を毎回走らせる」と時間がかかりすぎるので、変更のあった部分だけを狙って実行できるのはかなり重要です。
さらに、moonx というショートカット用のバイナリも、正式な単体実行ファイルとして安定したそうです。
加えて、IDを省略したときに対話式で project や task を選ぶプロンプトも入ったとのこと。これ、地味ですが現場では便利です。いちいちコマンドを全部書かなくても、候補から選べるのは気分がいいんですよね。
Moon の魅力の1つとして、task inheritance があります。
これは、ある project で定義した task を別の project に引き継いで使える仕組みです。モノレポでは似た構成のプロジェクトがたくさん出るので、毎回同じ設定を書くのはつらい。なので、この手の継承機能はかなり価値があります。
v2.0 では、これが ファイル名のルールに頼る方式から、設定ベースに変わりました。
新しい inheritedBy 設定を使って、toolchain、stack、language、tags などの条件で「どの project がどの task を継承するか」を決められます。
個人的には、これはかなり良い変更だと思います。
ファイル名の慣習に寄せすぎると、人間の記憶に依存しやすくて、あとで読むときに「なんでこの名前だっけ?」となりがちです。設定として明示されているほうが、意図が見えやすい。チーム開発ではこういう明文化が効きます。
さらに、task は 複数の toolchain に紐づけられるようになったそうです。
これも polyglot なモノレポ、つまり Node.js / Rust / Go みたいに複数言語が混在する現場ではありがたいはずです。
.env ファイルの扱いも改善されています。
.env.local や環境別のファイルを自動で読み込むようになり、さらに graph を作る時点ではなく、実行時に読み込むようになりました。
ここは少しニッチに見えて、実は重要です。
モノレポ系ツールは「依存関係グラフ」を作るときに設定を先読みしがちですが、環境変数の扱いが早すぎると、実行時の状況とズレることがあります。遅延ロードに寄せたのは、挙動をより現実に合わせた調整だと見てよさそうです。
Docker については、projectごとの上書き設定と、Tera ベースのカスタム Dockerfile template が追加されています。
Dockerfile template を柔軟にいじれるのは、コンテナ運用が当たり前になった今かなり嬉しい変更です。どのチームも「標準化したいけど、完全には揃わない」ので、こういう逃げ道は大事です。
VCS、つまり version control system(要するに Git まわり)の層も書き換えられています。
新しい Git 実装は worktree や submodule のサポートがより良くなったとのことです。
worktree は、1つの Git リポジトリから複数の作業ディレクトリを扱う仕組み。
submodule は、別リポジトリを内部に組み込む仕組みです。どちらも便利ですが、扱いはやや面倒です。そこをちゃんと見直したのは、実務感のある改善だと思います。
hooks system も変わっていて、もう .git/hooks に直接書き込まないそうです。
この変更は、Git の内部をいじる怖さを減らす方向だと読めます。地味だけど、安全性や保守性の観点ではかなり大事です。
当然ながら、こういう大改修のあとには breaking changes がつきものです。
Moon では moon migrate v2 という移行用コマンドが用意されていて、できるだけ自動化してくれるようです。
ただし、変更点は少なくありません。
moon upgrade は配布形式の変更で使えないここは正直、アップグレードのハードルは低くないです。
でも、プロダクトの土台を大きく変えたなら、これはある意味しかたない面もあります。むしろ中途半端に互換性を残して中身がぐちゃぐちゃになるより、きちんと切り替えたほうが長期的には良い、という判断なのかもしれません。
記事では、Moon はモノレポツール群の中で独特の位置にあると紹介されています。
Bazel ほど高機能すぎず、make や just ほど単純すぎない。つまり、そこそこ構造化されていて、しかも実用的なところを狙っているわけです。
比較としては、Turborepo や Nx の名前が挙がっています。
コミュニティ規模はまだ彼らより小さく、週あたりのダウンロード数もかなり差があるようですが、PkgPulse では Moon を「polyglot repos に向いた sleeper pick」と表現していたとのこと。
sleeper pick というのは、派手じゃないけど実はかなり良い選択肢、というニュアンスです。これはわりとしっくり来ます。
さらに、mise の作者 Jeff Dickey は、Hacker News で「mise は tool の問題を解決するために始まり、moon は build の問題を先に解いた」とコメントしたそうです。
この見方も面白いですね。つまり両者は真正面からぶつかるというより、役割が少し違って補完関係にあるということです。
Moon v2.0 は、単なるマイナーアップデートではありません。
toolchain のプラグイン化、設定形式の多様化、CLI の再整理、task inheritance の再設計と、かなり本気で土台を作り直しています。
特に印象的なのは、単に機能を増やすのではなく、拡張しやすさと現場での扱いやすさを強く意識していることです。
モノレポは一度大きくなると、あとから仕組みを変えるのが本当に大変です。その意味で、Moon が v2.0 で「閉じた内蔵機能」から「開いたプラグイン基盤」へ舵を切ったのは、かなり重要な一歩だと思います。
ただし、移行は簡単ではありません。
v1 を使っているチームは、アップデート前に migration guide を丁寧に読む必要があります。ここを雑に進めると、たぶん普通に痛い目を見るでしょう。
でも、ちゃんと移行できれば、より柔軟で長く使えるモノレポ基盤になるのではないか、という期待はかなり持てます。
参考: Moonrepo Releases Moon v2.0 with WASM Plugin Toolchains and Overhauled CLI