Tech Blog

Windows で Maven / Node / Java を PATH 依存なく動かすプロジェクト内完結構成

Windows Maven Node.js Spring Boot

はじめに

「新しいメンバーが参加したら、まず Java と Node.js と Maven のバージョン合わせから始まる」

チームではなく個人開発でも、PCを変えたとき・環境をリセットしたときに同じ問題が起きます。

このプロジェクトでは、Maven・Node・npm をプロジェクトフォルダ内に閉じ込め、
システムの PATH に依存しない構成を採用しました。


構成の概要

dvd-rental-admin/
  mvnw          ← Maven Wrapper(macOS/Linux用)
  mvnw.cmd      ← Maven Wrapper(Windows用)
  node/
    npm         ← npm(macOS/Linux用)
    npm.cmd     ← npm(Windows用)
    npx
    npx.cmd
  package.json  ← frontendビルド用のnpm設定

ビルドコマンドを実行するとき、システムにインストールされたMaven・Nodeを使うのではなく、
プロジェクト内のコマンドを使います。


Maven Wrapper

mvnw / mvnw.cmd は Maven Wrapper です。
実行すると、.mvn/wrapper/maven-wrapper.properties に記載されたバージョンのMavenを自動ダウンロードして実行します。

# .mvn/wrapper/maven-wrapper.properties
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip

使い方

# システムのMavenではなく、プロジェクト指定バージョンを使う
.\mvnw.cmd clean package

# システムに mvn コマンドがなくてもビルドできる

作成方法

# 既存Mavenがある環境でwrapperを生成
mvn wrapper:wrapper -Dmaven=3.9.6

Node / npm をプロジェクト内に閉じ込める

npm install でプロジェクト内に Node をインストール

node フォルダに Node.js バイナリを配置することで、システムの Node と分離します。

// package.json
{
  "engines": {
    "node": ">=22.0.0"
  },
  "scripts": {
    "build:css": "node/npm.cmd run tailwind",
    "build:ts": "node/npx.cmd tsc"
  }
}

または frontend-maven-plugin を使う方法:

<!-- pom.xml -->
<plugin>
    <groupId>com.github.eirslett</groupId>
    <artifactId>frontend-maven-plugin</artifactId>
    <version>1.15.0</version>
    <configuration>
        <installDirectory>node</installDirectory>  <!-- プロジェクト内の node/ に配置 -->
        <nodeVersion>v22.0.0</nodeVersion>
    </configuration>
    <executions>
        <execution>
            <id>install-node-and-npm</id>
            <goals><goal>install-node-and-npm</goal></goals>
        </execution>
    </executions>
</plugin>

mvn generate-resources を実行すると node/ フォルダに Node.js がインストールされます。


Windows でのパス解決の注意点

Windows では .cmd 拡張子が重要です。

# NG: 拡張子なしはWindows Powershellで動かないことがある
.\mvnw clean package

# OK: .cmd を明示する
.\mvnw.cmd clean package
.\node\npm.cmd run build

また、作業ディレクトリがプロジェクトルートでないと .\mvnw.cmd が解決に失敗します。

# NG: サブフォルダにいる場合
cd infra/cdk
.\mvnw.cmd package  # ← エラー:mvnw.cmd が見つからない

# OK: プロジェクトルートに戻ってから実行
cd C:\Users\y_104\git\dvd-rental-admin
.\mvnw.cmd package

# または絶対パスで実行
C:\Users\y_104\git\dvd-rental-admin\mvnw.cmd package

VS Code タスクの設定

VS Code の .vscode/tasks.json に定義しておくと、ターミナルを開かずにビルドできます。

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "build-backend",
      "type": "shell",
      "command": ".\\mvnw.cmd",
      "args": ["-DskipTests", "package"],
      "options": {
        "cwd": "${workspaceFolder}"  // ← workspaceFolderを明示
      },
      "group": "build"
    },
    {
      "label": "build-frontend",
      "type": "shell",
      "command": ".\\node\\npm.cmd",
      "args": ["run", "build"],
      "options": {
        "cwd": "${workspaceFolder}"
      },
      "group": "build"
    }
  ]
}

.gitignore の設定

プロジェクト内のNode・Mavenのキャッシュはコミットしません。

# Maven Wrapper のダウンロードキャッシュ
.mvn/wrapper/maven-wrapper.jar  # JARは除外(Wrapperが自動DLするため)

# Node バイナリ(frontend-maven-plugin がDL)
node/node_modules/
node/node.exe
node/npm
node/npm.cmd
node/npx
node/npx.cmd

# ただし node/ フォルダ自体は追跡する(空ディレクトリとして)

チームへの展開(オンボーディング)

この構成にしておくと、新しい環境でのセットアップが次のコマンドだけになります:

# 1. リポジトリをクローン
git clone https://github.com/your-org/dvd-rental-admin.git
cd dvd-rental-admin

# 2. Node をインストール(frontend-maven-plugin が自動DL)
.\mvnw.cmd generate-resources

# 3. フロントエンドビルド
.\node\npm.cmd install
.\node\npm.cmd run build

# 4. バックエンドビルド・起動
.\mvnw.cmd spring-boot:run

Java のバージョン指定は .sdkmanrc(SDKMAN使用時)または .java-version(jenv使用時)で管理します。


まとめ

問題解決策
システムのMavenバージョンが合わないmvnw / mvnw.cmd を使う
システムのNode/npmが使えない・バージョンが合わないfrontend-maven-plugin でプロジェクト内DL
.\mvnw.cmd がWindowsで動かない作業ディレクトリをプロジェクトルートにする
新メンバーの環境構築が複雑プロジェクト内完結構成にするとclone→buildが最小ステップ

「このプロジェクトをビルドするために必要なものはすべてこのフォルダにある」
という状態にすることで、環境差異によるトラブルを大幅に削減できます。


このシリーズの記事マップ

dvdrental 管理アプリと対になるエンドユーザー向けDVDレンタルアプリを作っている話 — Vue 3 + Spring Boot の全体構成と記事マップ

気軽にメッセージください

技術相談・ご感想・ご質問があればメッセージをお願いします。