Back

npm から pnpm に乗り換えるべきか?

npm から pnpm に乗り換えるべきか?

モノレポのセットアップ、CI 設定、フレームワークのドキュメントなどで pnpm が言及されているのを目にしたことがあるでしょう。あるいは、同僚が熱心に勧めているかもしれません。しかし、実際に日々のフロントエンド業務において、乗り換えの労力に見合う価値があるのでしょうか。それとも、まだ存在しない問題を解決しようとしているだけなのでしょうか。

ここでは、知っておくべき要点をお伝えします。

要点まとめ

  • pnpm はコンテンツアドレス可能なストアとハードリンク・シンボリックリンクを利用しており、ファントム依存関係を排除し、複数プロジェクトにわたるディスク使用量を削減します。
  • pnpm 11 では、pnpm 10 で導入されたライフサイクルスクリプトの制限が引き続き有効であり、pnpm approve-builds による明示的な承認を必須とすることで、サプライチェーンリスクを低減します。
  • ワークスペースのフィルタリングと workspace:* プロトコルにより、Turborepo や Nx を用いたモノレポに pnpm は非常によく適合します。
  • package.jsonpackageManager フィールドでパッケージマネージャを固定し、CI では --frozen-lockfile を使用して決定論的なインストールを行いましょう。
  • pnpm はモノレポや複数プロジェクト構成で真価を発揮します。単一パッケージのアプリであれば、npm を使い続けても問題ない場合が多いです。

pnpm と npm の本質的な違い

pnpm は単に高速な npm というわけではありません。本質的な違いは構造にあります。

npm はフラットな node_modules ディレクトリを作成するため、依存関係として宣言していないパッケージをコード内で誤ってインポートしてしまうことがあります。これがファントム依存関係(phantom dependencies)と呼ばれる問題です。pnpm はコンテンツアドレス可能なストアとハードリンク・シンボリックリンクを使用するため、ルートレベルで利用可能なのは宣言された依存関係のみとなります。これにより、依存関係の解決がより厳格かつ再現可能になります。

もう一つの大きな違いはディスク使用量です。pnpm は各パッケージバージョンをグローバルに一度だけ保存し、それをプロジェクトにハードリンクします。複数の Next.jsVite プロジェクトをローカルで管理している場合でも、数百メガバイトを各プロジェクトごとに重複保存することはありません。

ストレージモデルと依存関係の隔離についてより詳しく知りたい方は、公式の pnpm vs npm 比較 を一読する価値があります。

pnpm 11 とセキュリティ最優先へのシフト

2026 年 4 月にリリースされた pnpm 11 は、近年のメジャーバージョンで積み重ねられてきた傾向、すなわち生の速度よりもセキュリティと決定論性を優先するという方向性を継続しています。

乗り換え前に知っておくべき最も重要な挙動はこれです: pnpm は明示的に承認されない限り、依存関係のライフサイクルスクリプトをデフォルトでブロックするようになりました。 これは pnpm 10 で導入された pnpm approve-builds ワークフローです。postinstall スクリプトを含むパッケージ(sharpesbuildcanvas のようにネイティブバイナリをコンパイルするものに多い)をインストールした場合、インストール自体は成功しますが、承認するまでスクリプトは実行されません。

これは「とりあえず動く」ことを期待する開発者を驚かせる挙動です。pnpm approve-builds をインタラクティブに実行するか、pnpm-workspace.yaml で許可するビルド依存関係を設定してください:

onlyBuiltDependencies:
  - sharp
  - esbuild

これは意図的なトレードオフです。最初に多少の手間が増えるかわりに、後々のサプライチェーン上の予期せぬ事態を減らせます。

ワークスペースとモノレポツール

ここで pnpm は明確に一歩抜きん出ます。npm のワークスペースも機能しますが、pnpm のワークスペース実装はより大規模な構成に対して使い勝手が良いのです。

pnpm-workspace.yaml ファイルでパッケージを定義します:

packages:
  - 'apps/*'
  - 'packages/*'

そして、強力なフィルタリング機能を標準で利用できます:

pnpm --filter @myapp/ui build
pnpm --filter "...^@myapp/ui" test  # ui に依存するパッケージでテストを実行

TurborepoNx を使用するチームにとって、pnpm のワークスペースプロトコル(workspace:*)はクリーンに統合され、内部依存関係を明示的に保つことができます。

packageManager フィールドによるバージョン固定

Corepack を使うかどうかに関わらず、実用的なステップとして、プロジェクトが想定するパッケージマネージャとバージョンを示すために package.jsonpackageManager フィールドを追加しましょう。

{
  "packageManager": "pnpm@11.0.0"
}

Corepack はこれが有効化された環境でこの設定を強制できますが、Corepack なしでも、チームや CI 設定に対して意図を明確に伝える役割を果たします。

GitHub Actions による CI 統合

- uses: pnpm/action-setup@v6
  with:
    version: 11
- uses: actions/setup-node@v4
  with:
    node-version: 22
    cache: 'pnpm'
- run: pnpm install --frozen-lockfile

CI では必ず --frozen-lockfile を使用してください。これによりロックファイルの暗黙的な変更を防ぎ、インストールを決定論的にできます。

公式の pnpm CI ドキュメント には、GitHub Actions、GitLab CI、CircleCI、Azure Pipelines、Bitbucket Pipelines の例も掲載されています。

乗り換える価値があるケース

pnpm が最も意味を持つのは、モノレポで作業している場合、複数のローカルプロジェクトを管理している場合、あるいはデフォルトでより厳格な依存関係の隔離を求める場合です。pnpm approve-builds のセキュリティモデルは、サプライチェーンの衛生を重視するチームにとって本当に有用です。

単一パッケージのアプリを管理しており、npm が問題なく動作しているのであれば、移行の手間に見合うメリットはないかもしれません。npm ワークスペースはシンプルな構成には十分成熟していますし、エコシステムのデフォルトであることには依然として実質的な価値があります。

まとめ

率直に言えば、まずは新規プロジェクトで pnpm を試してみることをおすすめします。コマンドの体系はほぼ同じで、ロックファイルは読みやすく、Next.js、Vite、Astro を含むほとんどのフロントエンドフレームワークが追加設定なしでサポートしています。pnpm の厳格さとディスク容量の節約があなたのワークフローにフィットすると感じたら、既存プロジェクトへの展開はずっと小さな判断になるでしょう。

FAQ

通常は可能です。node_modules と package-lock.json を削除し、pnpm import を実行してロックファイルを変換した後、pnpm install を実行してください。npm のフラットなレイアウト下でコードが依存していたかもしれないファントム依存関係には注意が必要です。pnpm はそれらを欠落したインポートとして表面化させるので、package.json に明示的に追加して修正します。

approve-builds はライフサイクルスクリプトの実行を許可されたパッケージの許可リストです。このゲートを完全に無効にすることもできますが、それは pnpm 11 が緩和するために設計されたサプライチェーンリスクを再導入することになります。推奨される方法は、信頼でき、かつネイティブバイナリのコンパイラのように postinstall ステップが本当に必要なパッケージのみを承認することです。

大多数のパッケージは変更なしで動作します。問題が出るのは、フラットな node_modules 構造を前提とするパッケージや、ファントム依存関係に依存しているパッケージにほぼ限られます。人気のあるライブラリのほとんどは、これらをだいぶ前に修正済みです。万一壊れた場合、.npmrc の public-hoist-pattern 設定で特定のパッケージに対して npm スタイルのホイスティングを再現する逃げ道があります。

コールドインストールでは、並列解決とコンテンツアドレス可能なストアのおかげで pnpm は通常より高速です。依存関係を共有する複数プロジェクト間でのウォームインストールでは、pnpm はハードリンクを介してすでにダウンロード済みのパッケージを再利用するため、その差は劇的です。キャッシュが満たされた CI 環境では差は縮まりますが、pnpm は概してわずかに優位を保ちます。

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay