[Monoepo] PnPMを使ってモノレポを作る方法

2024-04-13 hit count image

NodeJSのパッケージマネージャの1つであるPnPMを使ってモノレポを作る方法について説明します。

概要

今回のブログポストではPnPMを使ってモノレポを作る方法について説明します。

ブログシリーズ

このブログはシリーズで作成されました。次のリンクを通じて他のブログポストも確認してください。

PnPM

PnPM は NodeJS のパッケージマネージャの 1 つで、NPMYarnと同じ役割をします。PnPMは高速なインストールとスペースの節約を強調し、さまざまなプロジェクトで使用されています。

PnPM のインストール

次のコマンドを使ってPnPMがインストールされたか確認します。

pnpm -v

インストールされていない場合は、次のコマンドを実行してPnPMをインストールします。

npm install -g pnpm

例題

PnPMをインストールしたら、PnPMを使ってモノレポを構成してみましょう。モノレポを構成するために、次のようなフォルダとファイル構造を作ります。

.
├── package.json
└── src
    ├── module-a
    │   ├── index.js
    │   └── package.json
    └── module-b
        ├── index.js
        └── package.json

module-apackage.jsonは次のようになります。

// src/module-a/package.json
{
  "name": "module-a",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  }
}

module-bpackage.jsonは次のようになります。

// src/module-b/package.json
{
  "name": "module-b",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  }
}

そしてmodule-bindex.jsは次のようになります。

// src/module-b/index.js
console.log('module-b');

最後にmodule-aindex.jsは次のようになります。

// src/module-a/index.js
console.log('module-a');

require('module-b');

このようにファイルを構成した後、次のコマンドを実行してモジュールを正しく読み込むか確認します。

node src/module-a/index.js

すると、次のようにエラーが発生することが確認できます。

module-a
node:internal/modules/cjs/loader:1073
  throw err;
  ^

Error: Cannot find module 'module-b'
Require stack:
- /Users/deku/temp/temp/src/module-a/index.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1070:15)
    at Module._load (node:internal/modules/cjs/loader:923:27)
    at Module.require (node:internal/modules/cjs/loader:1137:19)
    at require (node:internal/modules/helpers:121:18)
    at Object.<anonymous> (/Users/deku/temp/temp/src/module-a/index.js:3:1)
    at Module._compile (node:internal/modules/cjs/loader:1255:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1309:10)
    at Module.load (node:internal/modules/cjs/loader:1113:32)
    at Module._load (node:internal/modules/cjs/loader:960:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '/Users/deku/temp/temp/src/module-a/index.js' ]
}

pnpm-workspace.yaml

PnPMを使ってモノレポを構成するためには、pnpm-workspace.yamlファイルが必要です。ルートフォルダにpnpm-workspace.yamlファイルを作成し、次のように修正します。

packages:
  - 'src/*'

依存性のインストール

module-amodule-bを使ってるので、module-apackage.jsonファイルにmodule-bを依存性として追加する必要があります。依存性を追加するためにsrc/module-a/package.jsonファイルを開き、次のように修正します。

{
  "name": "module-a",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "module-b": "workspace:*"
  }
}

ファイルを修正したら、ルートフォルダで次のコマンドを実行して依存性をインストールします。

pnpm install

その後、フォルダ構造を確認すると、次のようにmodule-aフォルダ内のnode_modulesmodule-bSymlinkが作成されていることが確認できます。

.
├── node_modules
├── package.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── src
    ├── module-a
    │   ├── index.js
    │   ├── node_modules
    │   │   └── module-b -> ../../module-b
    │   └── package.json
    └── module-b
        ├── index.js
        └── package.json

Symlinkに関する詳細は次のリンクを参照してください。

確認

これでPnPMを使ってモノレポを使う準備が整いました。次のコマンドを実行してモジュールを正しく読み込むか確認します。

pnpm module-a start

すると、次のように正常に実行されることが確認できます。

module-a
module-b

module-anode_modulesmodule-bSymlinkが作成されたため、次のコマンドを使用することができます。

node ./src/module-a

module-bは依存性がないため、次のコマンドを実行すると問題なく実行されることが確認できます。

pnpm module-b start
# module-b
node ./src/module-b
# module-b

完了

これでPnPMを使ってモノレポを構成する方法について説明しました。Yarnを使わずにPnPMを使っている場合は、このブログポストを参考にしてPnPMでモノレポを構成してみてください。

私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!

アプリ広報

今見てるブログを作成たDekuが開発したアプリを使ってみてください。
Dekuが開発したアプリはFlutterで開発されています。

興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。

Posts