dependencies・devDependencies・peerDependenciesの違いと使い分け!

JavaScriptの開発では、npm installで必要なパッケージを追加します。

追加したパッケージはpackage.jsonに記録されますが、登録先にはdependenciesやdevDependencies、peerDependenciesなど、いくつかの種類があります。

「何が違うの?」「どこに登録すればよいの?」と迷うこともあるのではないでしょうか。

これらを使い分けるときは、アプリを動かすために必要なのか、開発中に使うものなのか、ライブラリを使う側に必要なパッケージと対応バージョンを伝えるものなのかに注目します。

この記事では、以下の内容をわかりやすく解説します。

  • dependenciesの役割
  • devDependenciesの役割
  • dependenciesとdevDependenciesの使い分け
  • peerDependenciesの役割

dependenciesとは?

dependenciesとは?

dependenciesとは、アプリを動かすために必要なパッケージを、package.jsonに記録する項目です。

例えば、アプリの日付処理にDay.jsというパッケージを使うとします。

その日付処理を動かすにはDay.jsが必要なので、アプリのdependenciesにdayjsを登録する必要があります。

Day.jsを追加するには、プロジェクトのフォルダで次のコマンドを実行します。

npm install dayjs

# 以下のコマンドでも可(--saveを付けても、dependenciesに登録される)
npm install --save dayjs

上記のコマンドを実行すると、Day.jsがインストールされ、package.jsonのdependenciesに登録されます。

登録される内容は、例えば次のようになります。バージョン番号は説明用です。

{
  "dependencies": {
    "dayjs": "^1.11.0"
  }
}

^1.11.0は「指定したバージョンの範囲(1.11.0以上、2.0.0未満)にあるDay.jsを使う」という意味です。

あわせて読みたい

npm installコマンドについては、以下の記事で詳しく説明しています。興味のある方は下記のリンクからぜひチェックをしてみてください。

devDependenciesとは?

devDependenciesとは?

devDependenciesとは、開発中のテストやビルドなどに使うパッケージを、package.jsonに記録する項目です。

プログラムが正しく動くかを確認するテストツールは、開発中に使います。

このような開発中のテストやビルドなどに使うパッケージはdevDependenciesに登録します。

例えば、テストツールのVitestを追加する場合は、次のコマンドを実行します(--save-devは、追加するパッケージをdevDependenciesに保存するオプションです)。

npm install --save-dev vitest

上記のコマンドを実行すると、Vitestがインストールされ、package.jsonのdevDependenciesに登録されます。

例えば、先ほどのDay.jsに加えてVitestをインストールすると、package.jsonは次のようになります。バージョン番号は説明用です。

{
  "dependencies": {
    "dayjs": "^1.11.0"
  },
  "devDependencies": {
    "vitest": "^4.0.0"
  }
}

npm install パッケージ名とnpm install --save-dev パッケージ名との違いは、package.json内の登録先です。

コマンド登録先
npm install パッケージ名dependencies
npm install --save-dev パッケージ名devDependencies

「dependencies」と「devDependencies」の使い分け

npm installは、パッケージ名を付けるかどうかで、使う場面が異なります。

コマンド主な用途
npm install dayjsDay.jsをプロジェクトに追加する
npm installプロジェクトの設定に記録されたパッケージをまとめてインストールする

新しいパッケージを追加するときは名前を付けます。すでにあるプロジェクトで必要なものをそろえるときは、名前を付けずにnpm installを実行します。

npm installを実行すると、dependenciesとdevDependenciesに記載されているパッケージがインストールされます。先ほどのpackage.jsonの例なら、Day.jsもVitestもインストールされます。

しかし、本番環境では、開発用のパッケージを除外してインストールしたい場合があります。

例えば、次のコマンドを実行すると、開発用のパッケージ(devDependenciesに記載されているパッケージ)を除外してインストールすることができます。

npm install --omit=dev

先ほどのpackage.jsonの例なら、上記のコマンドを実行すると、Day.jsはインストールされますが、Vitestはインストールされません。

もし、アプリを動かすために必要なDay.jsをdevDependenciesに登録していたら、この方法でインストールした環境では、Day.jsがインストールされないので、日付処理が動かなくなる可能性があります。

このように、「アプリを動かすために必要なもの(dependenciesに記載されているパッケージ)」と「開発作業で使うもの(devDependenciesに記載されているパッケージ)」を分けて登録することが大切です。

基本的には、次のように考えると整理しやすくなります。

必要になる場面登録先
アプリの機能を動かすために必要dependencies
開発中のテストやビルドなどに必要devDependencies

利用するライブラリのdevDependenciesはインストールされない

ここまでは、自分のアプリのpackage.jsonについて説明しました。

次は、インストールするライブラリ側のpackage.jsonを見てみましょう。

ここでは一例として、日付処理を行う架空のライブラリdate-helperがあるとします。

このdate-helperは、日付処理にDay.jsを使い、開発中のテストにはVitestを使っているとします。登録内容は、次のとおりです。

パッケージ用途登録先
dayjs日付処理を動かすdependencies
vitest日付処理が正しいかテストするdevDependencies

自分のアプリにdate-helperを追加すると、日付処理に必要なDay.jsもインストールされます。

一方、Vitestはdate-helperの作者が開発中に使うものです。date-helperの日付処理を利用するだけなら、自分のアプリには必要ありません。

そのため、date-helperをインストールしても、date-helper側のdevDependenciesにあるVitestは自分のアプリにはインストールされません。

このように、npm installを実行したときにインストールされるのは、自分のプロジェクトの開発用パッケージです。利用するライブラリの開発用パッケージまで、すべてインストールされるわけではありません。

peerDependenciesとは?

peerDependenciesとは?

peerDependenciesとは、ライブラリの作者が「このライブラリは、このパッケージのこのバージョンと組み合わせて使ってください」と伝えるための項目です。

例えば、React向けのUIライブラリなら、「このライブラリはReactの18系・19系に対応しています」と指定できます。

peerDependenciesを書くのは、使われるライブラリ側です。ライブラリの作者が、自分のライブラリのpackage.jsonに記載します。アプリ本体のpackage.jsonには通常書きません。

ここでは、Reactを使うライブラリを一例に、次のような状況でのpeerDependenciesの役割を見てみましょう。

  • Reactで作ったアプリに、ボタンや入力欄などを追加できるUIライブラリを入れる。
  • このUIライブラリを、説明用にsample-uiと呼ぶ。
  • アプリはReactを使って画面を作り、sample-uiもReactを使ってボタンや入力欄を表示する。

アプリ側のpackage.jsonには、例えば次のように記載します。名前やバージョンは説明用です。

{
  "dependencies": {
    "react": "19.0.0",
    "react-dom": "19.0.0",
    "sample-ui": "^1.0.0"
  }
}

これは、「このアプリではreact、react-dom、sample-uiを使う」という設定です。

一方、sample-uiの作者は、ライブラリ側のpackage.jsonに、次のように記載します。

{
  "name": "sample-ui",
  "version": "1.0.0",
  "peerDependencies": {
    "react": "^18.0.0 || ^19.0.0",
    "react-dom": "^18.0.0 || ^19.0.0"
  }
}

||は「または」という意味です。

この設定は、利用するアプリに対して、次の条件を伝えています。

このUIライブラリは、ReactとReact DOMの18系または19系に対応しています。対応するバージョンと組み合わせて使ってください。

今回のアプリはReactとReact DOMの19.0.0を使っているので、この条件を満たしています。なお、ReactとReact DOMは、両者のバージョンも整合させる必要があります。

なぜ「dependencies」ではなく「peerDependencies」に書くのか

ここで、「sample-uiを動かすためにReactが必要なら、ライブラリ側のdependenciesに登録すればよいのでは?」と思うかもしれません。

しかし、その場合、アプリ側のReactとは別に、ライブラリ側で使うReactがインストールされることがあります。

例えば、アプリが使うReactと、ライブラリがdependenciesで要求するReactのバージョンが合わない場合です。

設定する場所dependenciesの指定
アプリ側"react": "19.0.0"
UIライブラリ側"react": "^18.0.0"

UIライブラリはReactの18系を要求しているため、アプリ側の19.0.0では条件を満たせません。

この場合、npmは、ライブラリ用に18系を別にインストールします。例えば次のようになります。

アプリ
└─ node_modules
   ├─ react(19.0.0)
   └─ sample-ui
      └─ node_modules
         └─ react(18系)

この結果、アプリは19系、UIライブラリは18系という、別々のReactを使う状態になります。

同じ画面のコンポーネントと、それを描画するReact DOMが別々のReactを参照していると、エラーが発生することがあります。

そこで、UIライブラリ側ではReactをpeerDependenciesに指定します。

「このUIライブラリも、アプリ側と同じReactを使って動きます。そのReactは、対応するバージョンにしてください」と伝えるためです。

なお、dependenciesに書くと必ず別のReactが入るわけではありません。両方のバージョン条件を満たすものがあれば、共有される場合もあります。

対応していないバージョンが入っている場合

最初に紹介したpeerDependenciesの例では、アプリもUIライブラリもReactの19系を使えるため、条件が合っていました。

では、Reactの17系を使っているアプリに、18系・19系だけに対応するUIライブラリを追加するとどうなるでしょうか。

設定する側Reactの指定
アプリ側のdependencies"react": "17.0.2"
UIライブラリ側のpeerDependencies"react": "^18.0.0 || ^19.0.0"

この場合、アプリは「Reactの17.0.2を使う」と指定しています。一方、UIライブラリは「アプリ側でReactの18系か19系を使ってください」と求めています。

そのため、通常のnpmのインストールでは、このような条件の食い違いによってエラーになることがあります。

解決するには、例えば次のどちらかを検討します。

  • アプリ側のReactとReact DOMを、UIライブラリが対応するバージョンに更新する
  • Reactの17系に対応しているUIライブラリのバージョンを選ぶ

「peerDependencies」と「devDependencies」の両方に書くこともある

UIライブラリの作者も、開発中にはReactを使って動作確認やテストを行います。

そのため、同じReactをpeerDependenciesとdevDependenciesの両方に書くことがあります。

例えば、ライブラリ側のpackage.jsonに次のように記載します。

{
  "peerDependencies": {
    "react": "^18.0.0 || ^19.0.0",
    "react-dom": "^18.0.0 || ^19.0.0"
  },
  "devDependencies": {
    "react": "19.0.0",
    "react-dom": "19.0.0"
  }
}

この2つは、目的が異なります。

項目役割
peerDependencies利用するアプリに、対応するReactの範囲を伝える
devDependenciesUIライブラリを開発・テストするために、Reactを用意する

つまり、peerDependenciesは利用するアプリへの条件、devDependenciesはライブラリの作者が開発に使うものです。

peerDependenciesは自動インストールされる?

npm 7以降では、peerDependenciesに指定されたパッケージは、原則として自動インストールされます。

例えば、Reactが入っていないアプリにUIライブラリを追加すると、必要なReactも自動でインストールされることがあります。

条件に合うReactがすでに入っていれば、そのReactと組み合わせて使います。

つまり、アプリ側のdependenciesに直接書かれていなくても、ライブラリ側のpeerDependenciesの指定によって、必要なパッケージがインストールされる場合があります。

アプリ自身のコードでもReactを使うなら、アプリ側のdependenciesにもReactを登録して管理するのが基本です。

本記事のまとめ

この記事では、dependencies・devDependencies・peerDependenciesの違いと、その使い分けを説明しました。

項目主な役割
dependenciesアプリやライブラリを動かすために必要なパッケージを登録する
devDependencies開発中のテストやビルドなどに使うパッケージを登録する
peerDependenciesライブラリを使う側に、組み合わせるパッケージと対応バージョンを伝える

この記事のポイントは、次のとおりです。

  • dependenciesとdevDependenciesは、機能を動かすために必要か、開発作業で使うものかを基準に使い分ける。
  • 利用するライブラリのdevDependenciesは、自分のアプリには通常インストールされない。
  • peerDependenciesは、使われる側のライブラリが、使う側に求める条件を書くものである。
  • npm 7以降では、peerDependenciesに指定されたパッケージは原則として自動インストールされる。

お読みいただきありがとうございました。

スポンサーリンク