【実務・中級編】Mavenの「Reactor Build」を極める:特定のモジュールのみを高速に再ビルドする裏技 – ビルド・パッケージ管理ツール生産性向上バイブル

はじめに:なぜ、マルチモジュールビルドの「待ち時間」に魂を削るのか

マイクロサービスやドメイン駆動設計(DDD)の普及に伴い、Java界隈でもMavenを用いたマルチモジュール構成が標準的になりました。しかし、プロダクトが成長し、モジュール数が50、100と膨れ上がったとき、開発者の日常にある「不条理」が牙を剥きます。

「DTOを1行変更しただけなのに、なぜ全モジュールのテストが走り、3分間も待たされるのか?」

Mavenのデフォルトの挙動(ルートディレクトリでの `mvn clean install`)は、親モジュールから依存関係のグラフを逆算し、すべてのサブモジュールを直列あるいは並列で舐め尽くします。これはCI/CDパイプラインや初回ビルドにおいては正しい挙動ですが、日々のコーディング・デバッグサイクル(いわゆる内側ループ / Inner Loop)においては、開発者の認知負荷を高め、フロー状態を強制的に破壊する最悪のボトルネックです。

本記事では、Mavenの心臓部である「Reactor(リアクター)」のメカニズムを解剖し、変更したモジュールとそれに依存するパスだけを外科手術のように正確に抜き出して超高速ビルドを実現するCLIテクニックと、チーム全体の生産性を底上げするアーキテクチャ設計を伝授します。

—

1. Maven Reactorの内部挙動:なぜ全体ビルドは遅いのか

Mavenを起動すると、まず最初に `DefaultMavenExecutionRequest` が走り、プロジェクト内の `pom.xml` を再帰的にスキャンして「Reactor(ビルド対象の実行計画グラフ)」を構築します。

デフォルトでは、プロジェクトルートで実行されたMavenは、DAG(有向非巡回グラフ)の末端から根に向かって、すべてのモジュールをビルドキューに積みます。たとえ1つのクラスしか変更していなくとも、Mavenのデフォルト状態では「全モジュールが汚染されている(可能性éesがある)」とみなされ、全モジュールのコンパイルと単体テストが実行されます。

この無駄を排除するためには、Mavenが内部で保持する依存関係グラフに対して、「どこを起点とし、どこを終点とするか」をCLI引数で明示的に指示する必要があります。

—

2. 実戦投入:`-pl` と `-am` を極めるピンポイントビルド

ここからが本題です。開発スピードを劇的に高めるためにマスターすべきは、Reactorのスコープを限定する以下の2つのフラグです。

  • `-pl` または `–projects` : ビルド対象とするモジュールを指定する
  • `-am` または `–also-make` : 指定したモジュールが依存している「上位(内側)のモジュール」も一緒にビルドする

シナリオ:ドメイン層の変更を瞬時に反映する

以下のような典型的なマルチモジュール構成を想定します。

my-enterprise-app (pom.xml – root)
┣ core-domain (モジュールA: ビジネスロジック)
┣ infrastructure-db (モジュールB: データベースアクセス。core-domainに依存)
┗ presentation-api (モジュールC: REST API。infrastructure-dbとcore-domainに依存)

ここで、`core-domain` 内のエンティティクラスを1つ修正したとします。このとき、API層 (`presentation-api`) まで含めた全モジュールをビルドする必要はありません。必要なのは、「`core-domain` と、それに依存している下流モジュールすべて」のビルドです。

この絶妙な依存関係の解決を、Mavenはコマンド一発で実現します。

core-domain と、core-domain に依存するすべてのモジュールをビルドする
mvn clean test -pl :core-domain -am

コマンドの解剖

  • `-pl :core-domain` : Reactorの対象を artifactId が `core-domain` のモジュール単体に絞ります(ディレクトリパス `./core-domain` でも指定可能ですが、artifactIdのコロン記法 `:${artifactId}` が最も堅牢です)。
  • `-am` (also-make) : 指定したモジュール(`core-domain`)が依存している親モジュールを遡るのではなく、「指定したモジュールを利用している下流(依存先)のモジュール」を自動的に検出してビルドチェーンに組み込みます。

> 注意(逆のフラグ):
> 逆に「あるモジュールが依存している上流(内側)のモジュール」をすべてビルドしたい場合は、`-amd` (`–also-make-dependents`) を使います。例えば、`presentation-api` をビルドする際に、それが依存している `core-domain` と `infrastructure-db` も同時にビルドしたい場合は以下のように指定します。
> `mvn test -pl :presentation-api -amd`

—

3. さらに加速させる:開発者のための神・設定とプラグイン

CLIの最適化に加え、開発環境側の設定を作り込むことで、ビルド時間はさらに限界まで短縮されます。

1. 変更のないテストをスキップする(ただしリスク管理を伴う)

ローカルでの即時フィードバックを得るため、単体テストを一時的にスキップする `-DskipTests` は常套手段ですが、マルチモジュールでは「影響範囲のテストだけ走らせる」のが理想です。
しかし、急ぎの開発時には以下のショートカット(エイリアス)をターミナルの設定(`.zshrc` / `.bashrc`)に仕込んでおくことを強く推奨します。

変更したモジュール単体のみをコンパイル&テスト(依存関係自動解決つき)
alias mvc=’mvn test -DskipTests’
alias mvpl=’mvn test -pl’

2. Maven Parallel Builds(並列ビルド)の活用

どうしても複数モジュールをビルドせざるを得ない場合やCI環境においては、Maven 3の隠れた強力な機能である並列ビルドを有効にします。

プロジェクトルートの `.mvn/maven.config` に以下の設定を記述します。これにより、チームメンバー全員が明示的な引数を忘れても、常に最適な並列度でビルドが実行されます。

.mvn/maven.config
CPUコア数の1.5倍のスレッドで並列ビルドを実行し、ビルド時間を物理的に削減する
-T 1.5C

ログの可読性を上げるため、スレッドごとにログを色分けして出力する
–style.color=always

—

4. チーム開発で絶対に共有すべき設定とベストプラクティス構成

個人のローカル環境でいくら高速化しても、チーム全体のMaven構成が汚染されていては意味がありません。マルチモジュールプロジェクトにおいて、Reactorの効率を最大化するプロジェクト構造のベストプラクティスを提示します。

理想的なディレクトリ構造と `.mvn` の配置

my-project/
┣ .mvn/
┃ ┣ extensions.xml # 拡張機能の設定(CI用キャッシュなど)
┃ ┗ maven.config # 先述の並列ビルドなどのデフォルト引数
┣ module-parent/
┃ ┗ pom.xml # 依存関係のバージョン管理(dependencyManagement)を集約
┣ module-core/
┃ ┗ pom.xml
┣ module-service/
┃ ┗ pom.xml
┗ pom.xml # ルートpom.xml(の定義)

1. `extensions.xml` によるビルドライフサイクルの最適化

Mavenの拡張機能を使用し、ローカルビルドの速度を劇的に向上させます。例えば、`maven-build-cache-extension` を有効にすると、ソースコードに変更がないモジュールのビルドを完全にスキップ(前回のビルド成果物をキャッシュから復元)してくれます。

以下のファイルをプロジェクトルートの `.mvn/extensions.xml` として配置してください。





org.apache.maven.extensions
maven-build-cache-extension
1.0.0

この拡張を入れた状態で、通常通りプロジェクト全体で `mvn verify` などを実行してみてください。2回目以降のビルドでは、変更のあったモジュール以外のビルドログに `[INFO] Cached build: success` と表示され、秒速でビルドが完了する圧倒的な体験が得られます。

—

おわりに:ツールに支配されず、ツールを使い倒す

マルチモジュールプロジェクトのビルドが遅いという問題は、多くの場合、Maven自体の性能限界ではなく、「人間がツールの実行計画(Reactor)をコントロールしていないこと」に起因します。

今回紹介した `-pl` と `-am`、そして `.mvn/` ディレクトリを活用した環境のコード化(Configuration as Code)を組み合わせることで、あなたの日々の開発サイクルから「無駄な待ち時間」という名のストレスを完全に排除することができます。

明日からのコーディングで、ぜひ `mvn test -pl : -am` を叩いてみてください。その瞬間に返ってくるレスポンスこそが、プロのエンジニアが手に入れた新しい自由です。

タイトルとURLをコピーしました