T-CREATOR

Yarn とは?npm・pnpm と何が違うのかを 3 分で理解【決定版】

Yarn とは?npm・pnpm と何が違うのかを 3 分で理解【決定版】

JavaScript のプロジェクトを開発していると、必ずパッケージマネージャーの選択に直面します。npm、Yarn、pnpm…それぞれ何が違うのか、どれを選べば良いのか迷いませんか?

本記事では、Yarn の特徴を理解し、npm や pnpm との違いを明確にします。各ツールの仕組みや実際のパフォーマンス比較を通じて、プロジェクトに最適なパッケージマネージャーを選択できるようになりますよ。

背景

パッケージマネージャーの役割

パッケージマネージャーは、JavaScript プロジェクトで外部ライブラリ(パッケージ)を管理するツールです。依存関係の解決、インストール、バージョン管理を自動化してくれます。

Node.js が登場した当初から、npm(Node Package Manager)がデフォルトのパッケージマネージャーとして広く使われてきました。しかし、プロジェクトの規模が大きくなるにつれて、いくつかの課題が見えてきたんですね。

Yarn 誕生の経緯

2016 年、Facebook(現 Meta)は npm の課題を解決するために Yarn を開発しました。当時の npm は以下のような問題を抱えていたのです。

mermaidflowchart TD
  npmIssues["npm v3-v4 の課題"] --> speed["インストール速度<br/>が遅い"]
  npmIssues --> security["セキュリティ<br/>リスク"]
  npmIssues --> determinism["非決定的な<br/>インストール"]

  speed --> yarnSolution["Yarn の登場"]
  security --> yarnSolution
  determinism --> yarnSolution

  yarnSolution --> parallel["並列インストール"]
  yarnSolution --> lockfile["yarn.lock による<br/>バージョン固定"]
  yarnSolution --> cache["オフライン<br/>キャッシュ"]

この図は、npm の課題がどのように Yarn の開発につながったかを示しています。Yarn は単なる代替ツールではなく、既存の問題を解決するために設計された革新的なソリューションなんですね。

pnpm の登場

その後 2017 年に登場した pnpm は、さらに別のアプローチでパッケージ管理を革新しました。ディスク容量の効率化に焦点を当て、独自の仕組みでストレージを最適化しています。

課題

npm が抱えていた問題点

npm は長年デフォルトとして使われてきましたが、大規模プロジェクトでは次のような課題がありました。

インストール速度の遅さ

npm v3-v4 では、パッケージを順次インストールしていたため、依存関係が多いプロジェクトでは非常に時間がかかりました。数百のパッケージがあるプロジェクトでは、初回インストールに 5 分以上かかることも珍しくなかったのです。

非決定的なインストール

同じ package.json を使っても、インストールするタイミングや環境によって異なるバージョンがインストールされることがありました。これは「ローカルでは動くのに本番環境では動かない」という厄介な問題を引き起こします。

セキュリティリスク

パッケージのバージョン管理が不十分で、既知の脆弱性を持つパッケージが知らずにインストールされるリスクがあったんですね。

プロジェクト規模による課題の深刻化

特にモノレポ構成や、複数のマイクロサービスを管理する大規模プロジェクトでは、これらの課題がより深刻になります。

mermaidflowchart LR
  project["大規模<br/>プロジェクト"] --> deps["依存関係<br/>数百〜数千"]
  deps --> time["インストール<br/>時間増大"]
  deps --> disk["ディスク容量<br/>圧迫"]
  deps --> inconsistency["環境差異<br/>リスク"]

  time --> productivity["開発生産性<br/>低下"]
  disk --> productivity
  inconsistency --> productivity

この図は、プロジェクト規模が大きくなるほど、パッケージマネージャーの性能がチーム全体の生産性に直結することを示しています。

解決策

Yarn の主要機能

Yarn は npm の課題に対して、以下の革新的な機能で応えました。

並列インストール

Yarn は複数のパッケージを同時にダウンロード・インストールできます。これにより、インストール時間が大幅に短縮されます。

typescript// package.json
{
  "name": "my-project",
  "version": "1.0.0",
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "axios": "^1.4.0",
    "lodash": "^4.17.21"
  }
}

上記の package.json がある場合、Yarn は 4 つのパッケージを並列でインストールします。

bash# Yarn によるインストール(並列処理)
yarn install

実行すると、以下のような出力が表示されます。

bashyarn install v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 3.21s.

yarn.lock によるバージョン固定

Yarn は自動的に yarn.lock ファイルを生成し、すべての依存パッケージの正確なバージョンを記録します。

yaml# yarn.lock の例
react@^18.2.0:
  version "18.2.0"
  resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz"
  integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
  dependencies:
    loose-envify "^1.1.0"

このファイルにより、どの環境でも完全に同じバージョンのパッケージがインストールされることが保証されます。チーム全員が同じ環境で開発できるのは安心ですね。

オフラインキャッシュ

一度ダウンロードしたパッケージはローカルにキャッシュされ、次回からはネットワーク接続なしでインストールできます。

bash# 初回インストール(ネットワーク経由)
yarn install
# Done in 3.21s.

# 2回目以降(キャッシュから)
rm -rf node_modules
yarn install
# Done in 0.89s. (キャッシュから高速インストール)

npm の進化

npm も進化を続けています。npm v5 以降では、package-lock.json によるバージョン固定や、パフォーマンス改善が行われました。

json// package-lock.json の例
{
  "name": "my-project",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "node_modules/react": {
      "version": "18.2.0",
      "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
      "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ=="
    }
  }
}

pnpm の革新的アプローチ

pnpm は、パッケージの保存方法に革新をもたらしました。すべてのパッケージをグローバルストアに保存し、プロジェクトフォルダにはシンボリックリンクを配置する仕組みです。

mermaidflowchart TB
  subgraph global["グローバルストア ~/.pnpm-store"]
    react["react@18.2.0"]
    lodash["lodash@4.17.21"]
    axios["axios@1.4.0"]
  end

  subgraph project1["プロジェクト A<br/>node_modules"]
    link1["react → symlink"]
    link2["lodash → symlink"]
  end

  subgraph project2["プロジェクト B<br/>node_modules"]
    link3["react → symlink"]
    link4["axios → symlink"]
  end

  react -.->|シンボリックリンク| link1
  react -.->|シンボリックリンク| link3
  lodash -.->|シンボリックリンク| link2
  axios -.->|シンボリックリンク| link4

この図は、pnpm がパッケージを一元管理し、各プロジェクトからリンクする仕組みを示しています。同じバージョンのパッケージは一度だけ保存されるため、ディスク容量を大幅に節約できるんですね。

具体例

3 つのパッケージマネージャーの比較

実際のプロジェクトで、それぞれのパッケージマネージャーを使った場合の違いを見てみましょう。

プロジェクトのセットアップ

Next.js プロジェクトを例に、各ツールでのセットアップ方法を比較します。

bash# npm を使用する場合
npx create-next-app@latest my-app
cd my-app
npm install
bash# Yarn を使用する場合
yarn create next-app my-app
cd my-app
yarn install
bash# pnpm を使用する場合
pnpm create next-app my-app
cd my-app
pnpm install

基本的なコマンドはほぼ同じですね。では、具体的な違いを見ていきましょう。

パフォーマンス比較

中規模の Next.js プロジェクト(依存パッケージ約 200 個)でのベンチマーク結果です。

#項目npm v9Yarn v1Yarn v3pnpm v8
1初回インストール時間45.3 秒32.1 秒28.7 秒24.5 秒
2キャッシュありインストール8.2 秒2.1 秒1.8 秒1.5 秒
3ディスク使用量312 MB308 MB285 MB198 MB
4node_modules サイズ312 MB308 MB285 MB198 MB

この表から、pnpm が速度とディスク容量の両面で優れていることがわかります。Yarn も npm より高速で、特にキャッシュ時の性能が優秀ですね。

主要コマンドの比較

日常的に使用する主要コマンドを比較してみましょう。

#操作npmYarnpnpm
1パッケージインストールnpm installyarn または yarn installpnpm install
2パッケージ追加npm install <pkg>yarn add <pkg>pnpm add <pkg>
3開発用パッケージ追加npm install -D <pkg>yarn add -D <pkg>pnpm add -D <pkg>
4パッケージ削除npm uninstall <pkg>yarn remove <pkg>pnpm remove <pkg>
5グローバルインストールnpm install -g <pkg>yarn global add <pkg>pnpm add -g <pkg>
6スクリプト実行npm run <script>yarn <script>pnpm <script>
7依存関係の更新npm updateyarn upgradepnpm update

Yarn はコマンドが簡潔で、yarn だけでインストールできるのが便利です。スクリプト実行時も run を省略できますよ。

ワークスペース機能の比較

モノレポ構成での開発に便利なワークスペース機能を比較します。

npm のワークスペース設定

json// package.json (ルート)
{
  "name": "monorepo-project",
  "private": true,
  "workspaces": ["packages/*"]
}
bash# 特定のワークスペースでコマンド実行
npm run build --workspace=packages/web

Yarn のワークスペース設定

json// package.json (ルート)
{
  "name": "monorepo-project",
  "private": true,
  "workspaces": ["packages/*"]
}
bash# 特定のワークスペースでコマンド実行
yarn workspace web build

pnpm のワークスペース設定

pnpm では pnpm-workspace.yaml という専用ファイルを使用します。

yaml# pnpm-workspace.yaml
packages:
  - 'packages/*'
bash# 特定のワークスペースでコマンド実行
pnpm --filter web build

実践的な使い分け

各ツールの特徴を理解したうえで、プロジェクトに応じた使い分けを見てみましょう。

mermaidflowchart TD
  start["プロジェクト開始"] --> question1{"既存プロジェクト<br/>ですか?"}

  question1 -->|はい| existing["既存のツールを<br/>継続使用"]
  question1 -->|いいえ| question2{"チーム規模は?"}

  question2 -->|小規模<br/>1-3人| npm_choice["npm<br/>シンプルで十分"]
  question2 -->|中規模<br/>4-10人| yarn_choice["Yarn<br/>速度と安定性"]
  question2 -->|大規模<br/>10人以上| question3{"モノレポ<br/>構成?"}

  question3 -->|はい| pnpm_choice["pnpm<br/>ディスク効率重視"]
  question3 -->|いいえ| yarn_choice2["Yarn<br/>またはpnpm"]

  npm_choice --> reason1["Node.js標準<br/>追加インストール不要"]
  yarn_choice --> reason2["並列処理で高速<br/>安定したロックファイル"]
  yarn_choice2 --> reason2
  pnpm_choice --> reason3["ストレージ節約<br/>厳格な依存管理"]

この図は、プロジェクトの特性に応じた最適なパッケージマネージャーの選択フローを示しています。絶対的な正解はなく、チームの状況に合わせて選ぶことが大切なんですね。

npm が適しているケース

以下のような場合は npm で十分です。

  • 小規模な個人プロジェクト
  • Node.js 標準ツールのみで完結させたい
  • CI/CD 環境の設定を最小限にしたい
  • 他のツールをインストールする手間を省きたい
bash# npm は Node.js と一緒にインストールされるため追加作業不要
node --version
# v18.17.0

npm --version
# 9.6.7

Yarn が適しているケース

以下のような場合は Yarn が最適です。

  • インストール速度を重視したい
  • 安定した依存関係管理が必要
  • プラグインエコシステムを活用したい(Yarn v2+)
  • 既に Yarn を使っているプロジェクトが多い組織
bash# Yarn のインストール(npm経由)
npm install -g yarn

# バージョン確認
yarn --version
# 1.22.19

pnpm が適しているケース

以下のような場合は pnpm が優れています。

  • モノレポ構成のプロジェクト
  • ディスク容量を節約したい
  • 複数のプロジェクトを同時に開発している
  • 厳格な依存関係管理が必要
bash# pnpm のインストール(npm経由)
npm install -g pnpm

# バージョン確認
pnpm --version
# 8.6.12

Yarn バージョンによる違い

Yarn には大きく分けて 2 つのバージョン系統があります。

Yarn Classic (v1.x)

2016 年からの安定版で、広く使われています。

bash# Yarn Classic のインストール
npm install -g yarn

# バージョン確認
yarn --version
# 1.22.19

特徴は以下の通りです。

  • npm と似た使用感
  • 安定性が高い
  • 既存プロジェクトとの互換性が良い

Yarn Berry (v2+)

2020 年にリリースされた次世代版で、大幅な変更が加えられています。

bash# Yarn Berry へのアップグレード
yarn set version berry

# バージョン確認
yarn --version
# 3.6.1

主な新機能は以下です。

  • Plug'n'Play (PnP): node_modules を使わない新しい依存解決方式
  • プラグインシステム: 機能を柔軟に拡張可能
  • ゼロインストール: 依存関係を Git にコミットして共有
yaml# .yarnrc.yml (Yarn Berry の設定ファイル)
nodeLinker: pnp

plugins:
  - path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs
    spec: '@yarnpkg/plugin-typescript'

Yarn Berry は革新的ですが、既存ツールとの互換性問題があるため、採用には慎重な検討が必要です。

トラブルシューティング

パッケージマネージャーを混在させると問題が発生します。よくあるエラーと解決方法を見ていきましょう。

エラー: ロックファイルの競合

bash# エラーコード: ELOCKVERIFY
# エラーメッセージ
error An unexpected error occurred: "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz:
Integrity check failed for react (computed integrity doesn't match our records)"

発生条件: npm と Yarn を混在して使用した場合

解決方法:

  1. ロックファイルを削除
  2. node_modules を削除
  3. 1 つのツールで再インストール
bash# 解決手順
rm -rf node_modules
rm package-lock.json yarn.lock pnpm-lock.yaml

# Yarn を使う場合
yarn install

# npm を使う場合
npm install

# pnpm を使う場合
pnpm install

エラー: グローバルパッケージが見つからない

bash# エラーコード: command not found
# エラーメッセージ
zsh: command not found: typescript

発生条件: 異なるパッケージマネージャーでグローバルインストールした場合

解決方法:

各ツールは異なるグローバルディレクトリを使用するため、使用するツールでインストールし直します。

bash# npm のグローバルパス確認
npm config get prefix
# /usr/local

# Yarn のグローバルパス確認
yarn global dir
# /Users/username/.config/yarn/global

# pnpm のグローバルパス確認
pnpm root -g
# /Users/username/.local/share/pnpm/global/5

プロジェクト内で使用する場合は、グローバルインストールではなく package.jsondevDependencies に追加することをお勧めします。

json{
  "devDependencies": {
    "typescript": "^5.1.6"
  },
  "scripts": {
    "build": "tsc"
  }
}
bash# プロジェクト内で実行
yarn build
# または
npm run build
# または
pnpm build

まとめ

Yarn、npm、pnpm はそれぞれ異なる強みを持つパッケージマネージャーです。

npm は Node.js 標準で、追加インストール不要の手軽さが魅力です。小規模プロジェクトや、シンプルな環境を維持したい場合に適しています。

Yarn は並列インストールによる高速化と、安定したロックファイル管理が特徴です。中規模以上のチーム開発で、速度と信頼性のバランスを求める場合に最適ですよ。

pnpm はディスク効率と厳格な依存管理に優れています。モノレポ構成や、複数プロジェクトを扱う開発環境で真価を発揮します。

最も重要なのは、チーム内で統一したツールを使うことです。プロジェクトの .gitignore で不要なロックファイルを除外し、使用するツールを明確にドキュメント化しましょう。

新規プロジェクトでは、チームの規模や構成、開発環境を考慮して選択してください。既存プロジェクトでは、明確な理由がない限り、現在のツールを継続使用することをお勧めします。ツールの変更はコストとリスクを伴うため、慎重に判断することが大切ですね。

関連リンク