パッケージマネージャーとして人気を集める「pnpm」。その導入時に生成される pnpm-lock.yaml は、npmの package-lock.json やyarnの yarn.lock とは仕組みが大きく異なります。本記事では、pnpmのロックファイルの特徴やnpmとの違い、プロジェクト運用上の注意点について初心者にも分かりやすく、具体例を交えて丁寧に解説します。

pnpm-lock.yamlとは?

pnpm-lock.yaml は、pnpmを使用したプロジェクトにおいて、依存関係の正確なバージョンを記録するためのロックファイルです。このファイルは、再現性のあるビルド(deterministic builds)を保証するために必要不可欠な役割を果たします。

ロックファイルとは?

ロックファイルは、開発者がインストールしたパッケージのバージョンや依存関係の情報を固定化するためのファイルです。これにより、チームの他のメンバーやCI環境でも同じ状態の依存関係を再現することができます。

たとえば、package.json にはバージョン指定が ^1.5.0 と書かれていても、実際には 1.5.3 がインストールされていた場合、ロックファイルにはその 1.5.3 の情報が記録されます。

pnpm-lock.yamlの特徴

  • YAML形式で記述されており、人間が読んでも比較的分かりやすい
  • 依存関係がフラットではなくリンク構造(ハードリンク)で管理される
  • node_modules/ は仮想的な構造で構築され、ディスク容量の節約にもつながる
  • .pnpm-store に一度ダウンロードしたパッケージをキャッシュするため、高速な再インストールが可能

npmとのロックファイルの違い

npmにも package-lock.json というロックファイルがありますが、pnpmとの間には以下のような違いがあります。

比較項目pnpm(pnpm-lock.yaml)npm(package-lock.json)
ファイル形式YAML形式JSON形式
重複パッケージ同じ依存が複数箇所で必要な場合でも、バージョンごとに1つだけ保持し、各所でリンク共有される依存するパッケージごとに重複してインストールされることがあり、同じバージョンでも複数コピーされる
ストレージ構造.pnpm-store に一元管理されたキャッシュを保存し、node_modules 内はハードリンクで仮想構造を構築。実ファイルは重複せず効率的。依存パッケージはすべて node_modules にコピーされ、プロジェクトごとに物理ファイルが重複しがち。
ファイルサイズ比較的コンパクト大きくなりがち
依存の再現性極めて高い高いが、構造的にズレやすい

ストレージ構造と重複パッケージの違いを詳しく解説

pnpmが他のパッケージマネージャーと大きく異なる点のひとつが、node_modules の構造とストレージ戦略です。

1. .pnpm-store によるキャッシュ管理

pnpmは、ダウンロードしたすべてのパッケージを .pnpm-store という専用のディレクトリに保存します。これはグローバルキャッシュのような役割を持ち、複数のプロジェクトで同じパッケージを使いまわすことができます。

~/.pnpm-store
└── v3
    └── files
        └── sha512-...

この仕組みにより、同じ依存パッケージを別のプロジェクトでも再利用でき、ネットワークアクセスやディスク使用量が大幅に削減されます。

2. ハードリンクによる node_modules 構築

pnpmは .pnpm-store にあるパッケージのファイルをハードリンクという仕組みで node_modules に展開します。つまり、ファイルは物理的には1つだけで、複数の場所から同じ実体を参照しています。

  • ディスク容量が節約できる
  • 同じバージョンの依存パッケージを何度もインストールする必要がない
  • 再現性のある構造を構築しやすい

3. 重複パッケージの扱い

npmでは、依存するモジュールごとに同じパッケージが繰り返しインストールされ、node_modules の階層が深くなることがあります(例:A > B > lodashA > C > lodash など)。

一方pnpmでは、バージョンが同じであれば1つのパッケージをすべての依存元と共有するため、同じバージョンの lodash は1回しか保存されず、必要な場所にリンクされるだけです。

このように、pnpmのストレージ構造と重複パッケージ管理は、パフォーマンス・省容量・保守性の面で大きなメリットがあります。

実際のファイルの一部例(pnpm-lock.yaml)

lockfileVersion: 5.4
importers:
  .:
    dependencies:
      axios: 1.5.0
packages:
  /axios/1.5.0:
    resolution: { integrity: sha512-xxxxxx }
    dev: false

このように、どのパッケージがどのバージョンで、どこから取得されたのかが明記されています。


初心者がつまずきやすいポイントと運用上の注意点

1. pnpm-lock.yaml を直接編集してはいけない

これはpnpmが自動生成・管理するファイルです。手動で変更すると、依存関係の整合性が崩れる原因になります。もし内容を変更したい場合は、package.jsonを更新してから pnpm install を実行しましょう。

2. チーム開発ではパッケージマネージャーを統一

プロジェクトで複数のパッケージマネージャーを使うと、node_modules/ の構造やロックファイルの整合性が保てず、トラブルの原因になります。

  • .npmrc を使ってバージョンを固定すると安心です:
package-manager=pnpm@8.15.3

3. CI/CD環境でもpnpmを使用

CIツール(GitHub Actions や GitLab CIなど)では、必ず pnpm install --frozen-lockfile を使用しましょう。これにより、ロックファイルと package.json の不整合を防ぎ、常に同じ依存関係でデプロイできます。

pnpm install --frozen-lockfile

この --frozen-lockfile オプションは、pnpm-lock.yaml の内容を絶対に変更しないことを保証するためのものです。具体的には、以下のような動作になります:

  • package.json に書かれた依存と pnpm-lock.yaml の内容が一致していない場合、エラーを出してインストールを中断します。
  • ロックファイルが存在しない場合や、古い内容のままで package.json が更新されている場合も、失敗します

これにより、本番環境やCI環境で依存関係が書き換わることを防ぎ、完全に同一の環境構築を実現できます。

※ 開発中に意図的に依存を更新する場合は、--frozen-lockfile を外して pnpm install を実行し、その後ロックファイルを確認・コミットしましょう。

4. Gitに必ずコミットしよう

pnpm-lock.yaml はチームの開発環境を保つための重要なファイルです。.gitignore に含めず、必ずリポジトリにコミットしてください。


補足:pnpmとnpmの速度・容量の違い

pnpmは依存関係を「ハードリンク」で管理するため、ディスク容量を大幅に節約できます。実際に同じ依存を複数のプロジェクトで使っても、物理的には1つのファイルしか存在しません。また、キャッシュを活かしてインストール速度も非常に高速です。

体感例

# 初回(キャッシュなし)
pnpm install     → 約8秒
npm install      → 約25秒

# 2回目(キャッシュあり)
pnpm install     → 約1秒
npm install      → 約10秒

まとめ:pnpm-lock.yamlはpnpmの強みを支える重要ファイル

pnpm-lock.yaml はpnpm特有の依存管理を実現するための中核ファイルであり、npmとは大きく構造が異なります。再現性・パフォーマンス・ストレージ効率を向上させる一方で、運用においてはツールの統一やCI設定の徹底が不可欠です。

初心者であっても、基本的なルール(手動で編集しない・Gitで管理する・CIで活用する)を押さえておけば安心して使えます。pnpmの特性を正しく理解して、スムーズなチーム開発につなげましょう。