Node.jsで開発するとき、外部のライブラリ(パッケージ)を使わないことはほぼありません。そのパッケージを管理するのがnpm(Node Package Manager)で、プロジェクトの情報や依存パッケージを記録するのがpackage.jsonです。この2つはNode.js開発の土台です。
基本はnpm installでパッケージを入れるだけですが、dependenciesとdevDependenciesの違い、^や~といったバージョン表記(semver)の意味、package-lock.jsonの役割を知らないと、「同じはずなのに動かない」「バージョンが勝手に上がった」といったトラブルにつながります。この記事では、実機で確認しながら、npmとpackage.jsonの基礎を整理します。
npm init -yでpackage.jsonを作り、npm install パッケージ名で追加します。- 本番でも使うものは
dependencies、開発時だけ使うものは-Dを付けてdevDependenciesに入れます。 - バージョンの
^3.0.1は「3系の範囲で更新可」、~3.0.1は「3.0系の範囲で更新可」、3.0.1は完全一致です。 package.jsonのscriptsにコマンドを登録し、npm run 名前で実行します。package-lock.jsonは実際に入った正確なバージョンを記録します。消さずにコミットします。- 本番やCIでは、ロックファイル通りに入れる
npm ciを使うと再現性が高まります。
インストールしたパッケージの読み込み方はrequireとimportの違い、Node.js本体のインストールは指定したバージョンをインストールする方法、ファイル操作はfsでファイルを読み書きする方法もあわせて参考になります。
package.jsonとは(プロジェクトの設定ファイル)
package.jsonは、プロジェクトの名前・バージョン・依存パッケージ・実行コマンドなどを記録するファイルです。これがあることで、他の人がnpm installするだけで同じパッケージをそろえられます。
{
"name": "my-app",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^3.0.1"
}
}
dependenciesは本番でも必要なパッケージ、devDependenciesは開発時だけ使うパッケージ、scriptsはよく使うコマンドの登録欄です。これらの意味を順に見ていきます。
npm init で作る
新しいプロジェクトでは、まずnpm initでpackage.jsonを作ります。-yを付けると、質問をすべて既定値で進めて即座に作成できます。
# 質問に答えながら作る npm init # すべて既定値で即作成する(-y) npm init -y
実機でも、npm init -yでname・version(1.0.0)・main(index.js)などを含むpackage.jsonが即座に生成されました。nameとversionはあとから手で編集できます。
パッケージを追加する(npm install)
パッケージを追加するにはnpm install パッケージ名を実行します。するとnode_modulesフォルダに実体がダウンロードされ、package.jsonのdependenciesに名前とバージョンが追記されます。
# パッケージを追加(dependencies に入る) npm install express npm i express # i は install の短縮形 # package.json に書かれた依存をまとめて入れる(名前なし) npm install # 特定バージョンを指定して入れる npm install express@4.18.2 # パッケージを削除する npm uninstall express
実機でも、npm installを実行するとpackage.jsonのdependenciesにパッケージ名と^3.0.1のようなバージョンが追記され、node_modulesとpackage-lock.jsonが作られました。名前を付けずにnpm installだけを実行すると、package.jsonに書かれた依存をまとめてインストールします(プロジェクトを受け取ったときの最初の操作です)。
dependencies と devDependencies の違い
パッケージには「本番でも動かすのに必要なもの」と「開発時だけ使うもの」があります。後者は-D(または--save-dev)を付けてdevDependenciesに分けて入れます。
# 本番でも使う(dependencies) npm install express # 開発時だけ使う(devDependencies)。-D を付ける npm install -D nodemon npm install --save-dev jest
実機でも、npm install -Dで入れたパッケージはdependenciesではなくdevDependenciesに分けて記録されました。テストツール(jest)、開発用サーバー(nodemon)、ビルドツールなどはdevDependenciesに入れます。こうしておくと、本番環境でnpm install --omit=devを使ったときに、開発専用パッケージを除いて軽くインストールできます。
【重要】semver:^ と ~ の意味
バージョンの先頭に付く^や~は、どこまでの自動更新を許可するかを表します。バージョンはメジャー.マイナー.パッチ(例:3.0.1)の3つの数字でできていて、これをセマンティックバージョニング(semver)と呼びます。
| 表記 | 意味 | 許可される更新(例 3.0.1) |
|---|---|---|
^3.0.1 |
メジャーを固定(既定) | 3.0.1 〜 3.x.x(4.0.0は不可) |
~3.0.1 |
マイナーまで固定 | 3.0.1 〜 3.0.x(3.1.0は不可) |
3.0.1 |
完全一致 | 3.0.1 のみ |
* |
すべて | どのバージョンでも(非推奨) |
npm installすると、既定では^が付きます。^は「互換性が保たれる範囲(メジャーが同じ)なら更新してよい」という意味です。バージョンを厳密に固定したいときは、数字だけを書くか、次に説明するpackage-lock.jsonに任せます。
scripts と npm run
よく使うコマンドはpackage.jsonのscriptsに登録すると、npm run 名前で実行できます。長いコマンドを覚えなくてよくなり、チームでも共有できます。
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest",
"build": "node build.js"
}
}
npm run dev # nodemon index.js が動く npm run build # node build.js が動く # start と test は run を省略できる npm start # npm run start と同じ npm test # npm run test と同じ # 登録済みスクリプトの一覧を見る npm run
実機でも、scriptsに登録したコマンドがnpm run 名前で実行でき、npm runだけで登録済みの一覧が表示されました。startとtestは特別で、runを省略してnpm start・npm testと書けます。node_modulesに入れたツール(jestなど)は、scriptsの中ではパスを書かずに名前だけで呼べます。
package-lock.json と npm ci
package.jsonの^3.0.1は「3系ならOK」という範囲の指定です。そのため、いつnpm installするかで実際に入るバージョンが変わることがあります。これを防ぐのがpackage-lock.jsonで、実際に入った正確なバージョンを記録します。
# 通常の install(package.json の範囲で解決し、lock を更新することがある) npm install # CI や本番では npm ci(package-lock.json 通りに正確に入れる) npm ci
実機で確認したところ、package-lock.jsonには実際に入ったパッケージの正確なバージョン(依存の依存まで含む)が記録されていました。このファイルがあることで、誰がいつnpm installしても同じバージョンをそろえられます。package-lock.jsonはGitにコミットし、消さないでください。本番やCIでは、ロックファイル通りに入れるnpm ciを使うと、より確実に同じ環境を再現できます(npm ciはnode_modulesを作り直すため、まっさらな環境向けです)。
グローバルインストール(-g)とnpx
プロジェクトではなく、パソコン全体でコマンドとして使いたいツールは-g(グローバル)で入れます。一方、一度だけ実行したいツールは、インストールせずにnpxで実行できます。
# パソコン全体にコマンドとして入れる npm install -g typescript # 一度だけ実行したい(インストール不要) npx create-react-app my-app # プロジェクト内のツールを npx で実行する npx jest
グローバルインストールは便利ですが、プロジェクトごとにバージョンがそろわなくなるため、ビルドやテストのツールはdevDependenciesに入れてnpxやnpm runで使うのがおすすめです。npxは、まだ入れていないパッケージも一時的に取得して実行できるため、create-react-appのような「最初の1回だけ使うツール」に向いています。
よくある失敗
package-lock.jsonを削除・無視する
これがあるからこそ全員が同じバージョンをそろえられます。Gitにコミットし、消さないでください。本番ではnpm ciを使います。
開発ツールをdependenciesに入れる
jestやnodemonなど開発時だけ使うものは-DでdevDependenciesに入れます。本番のインストールを軽くできます。
node_modulesをGitにコミットする
node_modulesはnpm installで復元できるため、コミットしません。.gitignoreに追加します。package.jsonとpackage-lock.jsonだけをコミットします。
^と~を理解せずバージョンが上がって動かなくなる
^はメジャーが同じ範囲で更新されます。厳密に固定したいなら数字だけを書くか、npm ciでロックファイル通りに入れます。
npm installとnpm ciを取り違える
開発で依存を追加するときはnpm install、本番やCIで再現したいときはnpm ciです。npm ciはpackage-lock.jsonが必須です。
よくある質問
dependencies、テストやビルドなど開発時だけ使うものがdevDependenciesです。npm install -D パッケージ名でdevDependenciesに入ります。本番ではnpm install --omit=devで開発用を除けます。^3.0.1なら3.0.1から3.x.xまで上がり、4.0.0には上がりません。~3.0.1はさらに狭く3.0.xまで、数字だけなら完全一致です。node_modulesはコミットせず、.gitignoreに入れます。npm install、本番やCIでpackage-lock.json通りに正確に再現したいときはnpm ciです。npm ciはロックファイルが必須で、node_modulesを作り直します。devDependencies)がおすすめです。パソコン全体でコマンドとして使いたいものだけ-gで入れます。一度きりの実行はnpxが便利です。まとめ
npm init -yでpackage.jsonを作り、npm installでパッケージを追加します。- 本番用は
dependencies、開発用は-DでdevDependenciesに分けます。 ^はメジャー固定、~はマイナー固定、数字だけは完全一致です。scriptsにコマンドを登録し、npm run 名前で実行します。package-lock.jsonは正確なバージョンの記録。消さずにコミットします。- 本番やCIでは
npm ciで再現性を高めます。
npmとpackage.jsonは、最初は呪文のように見えますが、「dependenciesとdevDependenciesの区別」「^と~の意味」「package-lock.jsonをコミットする」の3点を押さえれば、安定したNode.js開発の土台になります。

