現代のモノレポ戦略:npm Workspacesでコードの「分断」を「調和」に変える
こんにちは。大規模なプロジェクトになればなるほど、「共通ライブラリを修正したのに、アプリ側に反映されていない」「npmパッケージのバージョン不整合で地獄を見た」といった経験はありませんか?
開発環境のアーキテクトとして断言します。それは、ツールが悪いのではなく、「プロジェクトの境界線」の設計思想が最適化されていないだけです。
今日は、Node.js標準機能である`npm Workspaces`を使い、複数のプロジェクトを一つのリポジトリで「美しく」管理する方法を伝授します。これをマスターすれば、あなたの開発効率は劇的に向上し、もうバージョン管理の泥沼に足を取られることはなくなります。
—
1. なぜ「npm Workspaces」なのか?(設計思想)
これまでの開発では、共通ライブラリを別リポジトリで管理し、`npm publish`しては各プロジェクトで`npm install`し直すという手順を踏んでいたはずです。しかし、修正のたびにその往復をするのはあまりに非効率。
`npm Workspaces`は、「複数のパッケージを一つのプロジェクト空間に同居させ、シンボリックリンクを用いて擬似的に一箇所に存在させる」という魔法を実現します。
これにより、以下のメリットが手に入ります。
- Hoisting(ホイスティング)の最適化: 依存ライブラリをルート階層に集約し、重複を排除。
- シームレスな開発体験: ローカルにある共通ライブラリを、まるで`node_modules`にあるライブラリのように直接読み込める。
- 一括操作: `npm install` や `npm test` をルートから一度実行するだけで、全サブパッケージに波及させる。
—
2. 実践:モノレポのアーキテクチャを構築する
まずは、ディレクトリ構成を整理しましょう。今回は「共通コア」と「Webアプリ」というシンプルな構成を想定します。
ディレクトリ構造
my-monorepo/
├── package.json # ルートの設定(ワークスペースの定義)
├── packages/ # サブパッケージ格納場所
│ ├── core-lib/ # 共通ライブラリ
│ └── web-app/ # Webアプリケーション
└── node_modules/ # ルートにホイスティングされたライブラリ群
ルートの `package.json` を設定する
ルート階層で以下を実行し、ワークスペースを宣言します。
{
“name”: “my-monorepo”,
“private”: true, // ルート自体は公開しないためtrue
“workspaces”: [
“packages/” // packages配下のディレクトリを全てワークスペースとみなす
]
}
—
3. 依存関係のホイスティング:知っておくべき「魔法」と「罠」
`npm Workspaces`の最も重要な概念がHoisting(ホイスティング)です。
通常、各パッケージで`lodash`をインストールすると、それぞれの`node_modules`にコピーされますが、npmはこれをルートの`node_modules`に「持ち上げ(Hoist)」て一つにまとめます。
注意点:
もしサブパッケージAとBで、異なるバージョンのライブラリを要求した場合、npmは賢く解決しようとしますが、依存関係の競合(Dependency Hell)が発生することがあります。原則として、モノレポ内ではライブラリのバージョンを統一するのがベストプラクティスです。
—
4. 実際に動かしてみよう:HelloWorld的構成
ステップ1:共通ライブラリを作成
`packages/core-lib/package.json` を作成します。
{
“name”: “@my-repo/core”, // パッケージ名(これを使って参照する)
“version”: “1.0.0”,
“main”: “index.js”
}
`packages/core-lib/index.js`:
export const hello = () => “Hello from Core Library!”;
ステップ2:Webアプリから利用する
`packages/web-app/package.json` に依存関係を記述します。
{
“name”: “web-app”,
“dependencies”: {
“@my-repo/core”: “1.0.0” // ローカルのパッケージを直接指定
}
}
ステップ3:インストールと確認
ルートディレクトリで一度だけコマンドを実行してください。
npm install
これで、`web-app` の `node_modules` 内に、`@my-repo/core` へのシンボリックリンクが自動生成されます。`web-app` 側から `require(‘@my-repo/core’)` を呼び出せば、即座に修正が反映される開発環境が完成です。
—
5. CI/CDパイプラインを制する:ビルド順序制御
実務において重要なのは、「依存先から先にビルドする」という順序です。
`npm workspaces` では、ワークスペース内のコマンドを対象に実行できます。
全てのパッケージでビルドを実行(依存関係を考慮して並列実行されることが多い)
npm run build –workspaces
特定のパッケージのみ実行
npm run build -w packages/core-lib
CI/CD(GitHub Actions等)では、`nx` や `turbo` といったビルドキャッシュツールを併用することで、「変更があったパッケージのみをビルドする」という高度なパイプラインを構築するのが今のトレンドです。
—
最後に:なぜ今、これを学ぶのか
「なぜわざわざモノレポにするのか?」と聞かれたら、私はこう答えます。
「コードの境界線をコントロールできるエンジニアこそが、技術負債を最もコントロールできるからだ」と。
npm Workspacesは単なるディレクトリ管理ツールではありません。あなたのコードを「断片的な部品」から「調和のとれたエコシステム」へと昇華させるための第一歩です。
まずは、小さなディレクトリを二つ作るところから始めてみてください。その瞬間に、あなたの開発環境の景色がガラリと変わるはずです。さあ、最高の開発体験を始めましょう!