私は現在、Windows / Mac ともに fnm で Node.js を管理し、パッケージマネージャは npm に統一しています。Windows 側は PowerShell で運用しています。
チームや案件で地味にハマるのが、Node.js のバージョン差です。
- 自分の Mac では動くのに、Windows では落ちる
- Node 18 で作ったのに、誰かは 20 を使っている
- npm / pnpm の差で lockfile が荒れる
こういったトラブルは、技術力の問題というより 「管理方法が揃っていない」ことが原因になりがちです。
なお、Node.js のバージョン管理ツールとしては Volta の導入も当初は検討しました。Volta はプロジェクト単位で Node と npm / yarn などを固定しやすく、チーム運用では合理的とのことです。一方で私は独りまたは少人数で開発することが多く、まずは Node 管理を軽く保てる fnm + npm に落ち着きました。
この記事では、その前提で Windows / Mac 混在でも破綻しにくい Node.js 管理方法をまとめます。
結論:揃えるべきものは3つだけ
Windows / Mac 混在環境で足並みを揃えるために、最低限決めるべきことは次の3点です。
- Node.js のバージョン
- パッケージマネージャ(npm に統一)
- lockfile(package-lock.json)の運用ルール
ここが揃えば、OS や個人の環境差による事故はかなり減ります。
Node.js の管理は fnm で統一する
fnm を使っている理由
- Windows / Mac 両方で同じ考え方で運用できる
- Node の切り替えが速い
- プロジェクト単位での管理がシンプル
特別な思想を持ち込まず、「Node の管理にだけ集中できる」点が気に入っています。
Volta を選ばなかった理由(否定ではない)
Volta は、プロジェクト単位で Node と npm / yarn を pin して package.json で共有できるため、チームで「切り替え忘れ」を減らしたい場合に強い選択肢です(※ pnpm サポートは実験的で、環境変数の設定が必要です)。
一方で私の案件では、まず Node のバージョンが揃っていれば十分な場面が多く、ツールチェーンまで固定する運用を必須にしなくても回ります。そのため、より軽量に運用できる fnm + npm を選びました。
Volta が悪いわけではなく、「今回は選ばなかった」というだけです。
プロジェクト側で必ず揃える設定(ここが一番重要)
ツールよりも重要なのは、プロジェクト側に「揃う前提」を置くことです。
1) .node-version をコミットする
プロジェクトルートに .node-version を置きます。
例:
20.11.1
これだけで、
- このプロジェクトはどの Node を使うか
- Windows / Mac 問わず同じ前提
が明確になります。
2) package.json の engines を併用する
.node-version はツール向け、engines は人と CI 向けです。
{
"engines": {
"node": ">=20 <21"
}
}
※ engines は「想定レンジの宣言」で、設定次第では警告止まりになることがあります。強制したい場合は CI 側で担保するか、.npmrc の engine-strict などを検討してください。
3) npm に統一し、lockfile を正とする
パッケージマネージャは npm に統一します。
- lockfile は
package-lock.json - 必ずコミット
- 他の lockfile は使わない
npm の運用は次のように分けています。
- 依存関係変更時:
npm install - 通常・CI:
npm ci
これだけで依存関係のブレはかなり減ります。
README に書いておく最小手順(テンプレ)
環境構築は「考えなくていい」状態を作るのが理想です。
# Node.js をインストール(.node-version に合わせる)
fnm install
# 使用する Node を有効化
fnm use
# 依存関係のインストール
npm ci
# 開発
npm run dev
fnm の自動切り替え(ディレクトリ移動で .node-version / .nvmrc を見て切り替える)を使う場合は、PowerShell のプロファイル設定が必要です。設定していない場合は、上の手順どおりに fnm use を実行すれば問題ありません。
Windows / Mac 共通で動く手順にしておくと、新規参加や環境再構築が楽になります。
CI でも Node バージョンを揃える
ローカルと CI の Node が違うと、結局そこで事故が起きます。
GitHub Actions 例:
- uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
cache: 'npm'
- run: npm ci
- run: npm test
ここで最終的に「揃う」ようにしておくのが重要です。
よくある詰まりポイント
Node が二重管理になっている
- OS に直接入れた Node
- 以前使っていた別の管理ツール
これが残っていると、node -v の結果が人によって変わります。
Node は fnm だけ、と決めるのが安全です。
グローバル npm 依存
グローバルに入れたツールが原因で、環境差が出ることがあります。
できるだけ devDependencies に寄せ、プロジェクト依存にするほうが安定します。
まとめ:Node 管理は「揃える」ための作業
Node.js 管理の目的は「新しいことをする」ではなく、環境差による手戻りを減らすことです。
- Node は fnm で管理する
.node-versionをコミットしてプロジェクトの前提を揃える- npm と
package-lock.jsonを正として運用する - CI でも
.node-versionを参照して揃える
「最新かどうか」より、迷わず同じ手順で動くことを優先すると、実務はだいぶ楽になります。