Node.jsプロジェクトを始める際、最初に作成するのがpackage.jsonファイルです。このファイルはプロジェクトのメタデータ、依存関係、スクリプトなどを一元管理する設定ファイルであり、Node.js開発の基盤となります。本記事では、npm initによるプロジェクト初期化からpackage.jsonの詳細な構造、セマンティックバージョニング、npmスクリプトの活用方法までを体系的に解説します。

実行環境

項目 バージョン
Node.js 20.x LTS以上
npm 10.x以上
OS Windows/macOS/Linux

前提条件

  • JavaScriptの基礎文法を理解していること
  • ターミナル(コマンドライン)の基本操作ができること
  • Node.jsとnpmがインストール済みであること

バージョンは以下のコマンドで確認できます。

1
2
3
4
5
node -v
# v20.18.0

npm -v
# 10.8.2

npm initによるプロジェクト初期化

新しいNode.jsプロジェクトを始める際は、npm initコマンドを使用してpackage.jsonファイルを作成します。

対話形式での初期化

まず、プロジェクト用のディレクトリを作成し、移動します。

1
2
mkdir my-nodejs-project
cd my-nodejs-project

npm initコマンドを実行すると、対話形式でプロジェクト情報を入力できます。

1
npm init

以下のような質問が順番に表示されます。

1
2
3
4
5
6
7
8
9
package name: (my-nodejs-project)
version: (1.0.0)
description: My first Node.js project
entry point: (index.js)
test command: jest
git repository: https://github.com/username/my-nodejs-project
keywords: nodejs, tutorial
author: Your Name <your.email@example.com>
license: (ISC) MIT

各項目について説明します。

項目 説明 デフォルト値
package name パッケージ名(小文字、ハイフン区切り推奨) ディレクトリ名
version 初期バージョン 1.0.0
description プロジェクトの説明 空文字
entry point メインエントリーポイントファイル index.js
test command テスト実行コマンド 空文字
git repository Gitリポジトリ URL 空文字
keywords 検索用キーワード(カンマ区切り) 空配列
author 作者情報 空文字
license ライセンス ISC

すべての質問に回答すると、確認画面が表示されます。内容を確認して「yes」を入力すると、package.jsonファイルが生成されます。

クイック初期化

すべてデフォルト値で素早くpackage.jsonを作成したい場合は、-yフラグを使用します。

1
npm init -y

このコマンドを実行すると、対話なしで即座にpackage.jsonが生成されます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "name": "my-nodejs-project",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}

デフォルト値のカスタマイズ

npm configコマンドで、npm initのデフォルト値を事前に設定できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 作者名の設定
npm config set init-author-name "Your Name"

# 作者メールアドレスの設定
npm config set init-author-email "your.email@example.com"

# デフォルトライセンスの設定
npm config set init-license "MIT"

# 初期バージョンの設定
npm config set init-version "0.1.0"

設定した値はnpm config listで確認できます。

1
npm config list

package.jsonの構造を理解する

package.jsonはJSON形式のファイルで、プロジェクトに関するあらゆる情報を定義します。主要なフィールドを詳しく見ていきましょう。

基本フィールド

name(パッケージ名)

パッケージ名は以下のルールに従う必要があります。

  • 214文字以下
  • 小文字のみ使用(npmレジストリに公開する場合)
  • ハイフン(-)とアンダースコア(_)は使用可能
  • URLセーフな文字のみ使用
1
2
3
{
  "name": "my-awesome-project"
}

スコープ付きパッケージの場合は、@scope/package-name形式で指定します。

1
2
3
{
  "name": "@myorg/my-package"
}

version(バージョン)

セマンティックバージョニング(後述)に従ったバージョン番号を指定します。

1
2
3
{
  "version": "1.2.3"
}

description(説明)

プロジェクトの簡潔な説明を記述します。npmレジストリでの検索結果に表示されます。

1
2
3
{
  "description": "A fast and lightweight HTTP client for Node.js"
}

main(エントリーポイント)

パッケージがrequireまたはimportされたときに読み込まれるメインファイルを指定します。

1
2
3
{
  "main": "lib/index.js"
}

type(モジュールタイプ)

ES Modulesを使用する場合は"module"を指定します。CommonJSを使用する場合は"commonjs"(デフォルト)です。

1
2
3
{
  "type": "module"
}

実際のpackage.json例

典型的なNode.jsプロジェクトのpackage.jsonを見てみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
  "name": "express-api-server",
  "version": "1.0.0",
  "description": "RESTful API server built with Express",
  "main": "src/index.js",
  "type": "module",
  "scripts": {
    "start": "node src/index.js",
    "dev": "node --watch src/index.js",
    "test": "node --test",
    "lint": "eslint src/"
  },
  "keywords": ["express", "api", "rest", "nodejs"],
  "author": "Your Name <your.email@example.com>",
  "license": "MIT",
  "dependencies": {
    "express": "^4.21.0"
  },
  "devDependencies": {
    "eslint": "^9.0.0"
  },
  "engines": {
    "node": ">=20.0.0",
    "npm": ">=10.0.0"
  }
}

dependenciesとdevDependenciesの違い

package.jsonにおける依存関係管理は、Node.js開発で最も重要な概念の一つです。

dependencies(本番依存関係)

dependenciesには、アプリケーションの実行に必要なパッケージを記述します。これらは本番環境でも必要になるパッケージです。

1
2
3
4
5
6
7
{
  "dependencies": {
    "express": "^4.21.0",
    "dotenv": "^16.4.5",
    "cors": "^2.8.5"
  }
}

パッケージをdependenciesに追加するには、以下のコマンドを使用します。

1
2
3
npm install express
# または
npm install express --save

devDependencies(開発依存関係)

devDependenciesには、開発時にのみ必要なパッケージを記述します。テストフレームワーク、リンター、ビルドツールなどが該当します。

1
2
3
4
5
6
7
8
{
  "devDependencies": {
    "eslint": "^9.0.0",
    "prettier": "^3.3.0",
    "typescript": "^5.5.0",
    "@types/node": "^22.0.0"
  }
}

パッケージをdevDependenciesに追加するには、--save-devまたは-Dフラグを使用します。

1
2
3
npm install eslint --save-dev
# または
npm install eslint -D

使い分けの判断基準

以下の図は、依存関係の分類方法を示しています。

flowchart TD
    A[パッケージをインストールする] --> B{本番環境で必要?}
    B -->|はい| C[dependencies]
    B -->|いいえ| D{開発時に必要?}
    D -->|はい| E[devDependencies]
    D -->|いいえ| F[インストール不要]
    
    C --> G["npm install package"]
    E --> H["npm install -D package"]

具体的な例を挙げると以下のようになります。

パッケージ 種類 理由
express dependencies サーバー実行に必要
dotenv dependencies 環境変数読み込みに必要
eslint devDependencies コード品質チェックは開発時のみ
jest devDependencies テストは開発時のみ
typescript devDependencies コンパイルは開発時のみ

peerDependencies(ピア依存関係)

プラグインやライブラリを開発する場合、ホストパッケージとの互換性を示すためにpeerDependenciesを使用します。

1
2
3
4
5
6
{
  "name": "my-express-middleware",
  "peerDependencies": {
    "express": "^4.0.0 || ^5.0.0"
  }
}

optionalDependencies(オプション依存関係)

インストールに失敗しても問題ないパッケージはoptionalDependenciesに記述します。

1
2
3
4
5
{
  "optionalDependencies": {
    "fsevents": "^2.3.0"
  }
}

セマンティックバージョニングを理解する

セマンティックバージョニング(Semantic Versioning、略してSemVer)は、バージョン番号に意味を持たせる規約です。npmはこの規約に基づいてバージョン管理を行います。

バージョン番号の構造

セマンティックバージョニングでは、バージョン番号をMAJOR.MINOR.PATCHの3つの数字で表現します。

1
2
3
4
5
バージョン: 2.4.1
            │ │ │
            │ │ └── PATCH: 後方互換性のあるバグ修正
            │ └──── MINOR: 後方互換性のある機能追加
            └────── MAJOR: 後方互換性のない変更

各要素の意味は以下の通りです。

要素 変更タイミング
MAJOR 互換性のないAPI変更 1.0.0 → 2.0.0
MINOR 後方互換性のある機能追加 1.0.0 → 1.1.0
PATCH 後方互換性のあるバグ修正 1.0.0 → 1.0.1

バージョン範囲指定子

npmでは、依存パッケージのバージョンを柔軟に指定できます。

キャレット(^)

最も一般的な指定方法です。MAJOR バージョンを固定し、MINOR と PATCH のアップデートを許可します。

1
2
3
4
5
{
  "dependencies": {
    "express": "^4.21.0"
  }
}

この場合、4.21.0以上5.0.0未満の最新バージョンがインストールされます。

チルダ(~)

MAJOR と MINOR バージョンを固定し、PATCH のアップデートのみを許可します。

1
2
3
4
5
{
  "dependencies": {
    "lodash": "~4.17.21"
  }
}

この場合、4.17.21以上4.18.0未満の最新バージョンがインストールされます。

その他の指定方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "dependencies": {
    "exact-version": "1.2.3",
    "greater-than": ">1.2.3",
    "greater-or-equal": ">=1.2.3",
    "less-than": "<2.0.0",
    "range": ">=1.0.0 <2.0.0",
    "or-range": "1.2.x || 2.x",
    "any": "*",
    "latest": "latest"
  }
}

バージョン指定の比較表

指定 意味 1.2.3での許容範囲
^1.2.3 互換性のある変更を許可 >=1.2.3 <2.0.0
~1.2.3 パッチバージョンのみ許可 >=1.2.3 <1.3.0
1.2.3 厳密にこのバージョン 1.2.3のみ
1.2.x パッチバージョンは任意 >=1.2.0 <1.3.0
1.x マイナー以降は任意 >=1.0.0 <2.0.0
* 任意のバージョン すべて

プレリリースバージョン

開発中のバージョンには、プレリリース識別子を付加できます。

1
2
3
4
5
1.0.0-alpha      # アルファ版
1.0.0-alpha.1    # アルファ版の更新
1.0.0-beta       # ベータ版
1.0.0-beta.2     # ベータ版の更新
1.0.0-rc.1       # リリース候補版

プレリリースバージョンは、通常のバージョンよりも優先度が低くなります。

1
1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-rc.1 < 1.0.0

npmスクリプトの活用方法

package.jsonのscriptsフィールドを使用すると、よく使うコマンドをエイリアスとして定義できます。

scriptsフィールドの基本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "scripts": {
    "start": "node src/index.js",
    "dev": "node --watch src/index.js",
    "test": "node --test",
    "build": "tsc",
    "lint": "eslint src/",
    "format": "prettier --write src/"
  }
}

定義したスクリプトはnpm run <script-name>で実行できます。

1
2
3
4
5
6
7
8
# 開発サーバーを起動
npm run dev

# テストを実行
npm run test

# リントを実行
npm run lint

特別なスクリプト名

一部のスクリプト名には特別な意味があり、runを省略して実行できます。

スクリプト名 実行コマンド 用途
start npm start アプリケーション起動
test npm test または npm t テスト実行
stop npm stop アプリケーション停止
restart npm restart 再起動(stop → start)
1
2
3
4
5
6
7
8
# これらは同じ
npm start
npm run start

# これらも同じ
npm test
npm t
npm run test

ライフサイクルスクリプト

npmは特定のタイミングで自動的にスクリプトを実行します。

flowchart LR
    A[preinstall] --> B[install] --> C[postinstall]
    D[prepublish] --> E[prepare] --> F[prepublishOnly]
    G[prepack] --> H[pack] --> I[postpack]

代表的なライフサイクルスクリプトは以下の通りです。

スクリプト 実行タイミング
preinstall npm install実行前
install npm install実行時
postinstall npm install完了後
prepare npm install完了後、npm publish前
prepublishOnly npm publish前のみ
1
2
3
4
5
6
{
  "scripts": {
    "prepare": "husky install",
    "postinstall": "node scripts/setup.js"
  }
}

pre/postフック

任意のスクリプトにprepostプレフィックスを付けることで、前後に実行されるフックを定義できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "scripts": {
    "prebuild": "rm -rf dist",
    "build": "tsc",
    "postbuild": "cp package.json dist/",
    
    "pretest": "npm run lint",
    "test": "node --test",
    "posttest": "echo 'Tests completed!'"
  }
}

npm run buildを実行すると、以下の順序で実行されます。

  1. prebuild(distディレクトリを削除)
  2. build(TypeScriptコンパイル)
  3. postbuild(package.jsonをコピー)

スクリプトの連結と並列実行

複数のコマンドを組み合わせる方法があります。

順次実行(&&)

1
2
3
4
5
{
  "scripts": {
    "build": "npm run clean && npm run compile && npm run bundle"
  }
}

並列実行

npm-run-allパッケージを使用すると、スクリプトの並列実行が可能です。

1
npm install -D npm-run-all
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "scripts": {
    "lint:js": "eslint src/",
    "lint:css": "stylelint src/**/*.css",
    "lint": "run-p lint:*",
    "build:client": "vite build",
    "build:server": "tsc -p tsconfig.server.json",
    "build": "run-p build:*"
  }
}
コマンド 機能
run-s 順次実行
run-p 並列実行
run-s lint:* lint:で始まるすべてのスクリプトを順次実行
run-p build:* build:で始まるすべてのスクリプトを並列実行

環境変数とスクリプト

スクリプト内で環境変数を使用できます。

1
2
3
4
5
6
{
  "scripts": {
    "start:dev": "NODE_ENV=development node src/index.js",
    "start:prod": "NODE_ENV=production node src/index.js"
  }
}

Windowsでも動作させるには、cross-envパッケージを使用します。

1
npm install -D cross-env
1
2
3
4
5
6
{
  "scripts": {
    "start:dev": "cross-env NODE_ENV=development node src/index.js",
    "start:prod": "cross-env NODE_ENV=production node src/index.js"
  }
}

引数の受け渡し

スクリプトに引数を渡すには--を使用します。

1
2
3
4
5
# testスクリプトに引数を渡す
npm test -- --watch

# lintスクリプトに引数を渡す
npm run lint -- --fix

package.jsonでデフォルト引数を設定することもできます。

1
2
3
4
5
6
7
{
  "scripts": {
    "test": "node --test",
    "test:watch": "npm test -- --watch",
    "test:coverage": "npm test -- --experimental-test-coverage"
  }
}

enginesフィールドでNode.jsバージョンを指定する

プロジェクトが特定のNode.jsバージョンを必要とする場合、enginesフィールドで指定できます。

1
2
3
4
5
6
{
  "engines": {
    "node": ">=20.0.0",
    "npm": ">=10.0.0"
  }
}

この設定により、互換性のないNode.jsバージョンを使用している開発者に警告が表示されます。

.npmrcファイルでengine-strict=trueを設定すると、互換性のないバージョンでのインストールがエラーになります。

1
engine-strict=true

package-lock.jsonの役割

npm installを実行すると、package-lock.jsonファイルが自動生成されます。このファイルは以下の役割を持ちます。

  1. 再現性の確保: 依存関係の正確なバージョンを記録し、異なる環境でも同じバージョンがインストールされることを保証します
  2. 高速なインストール: 依存関係ツリーが事前に計算されているため、インストールが高速化されます
  3. セキュリティ: 各パッケージの整合性ハッシュ(integrity)を記録し、改ざんを検知できます

package-lock.jsonは必ずバージョン管理(Git)にコミットしてください。

1
2
3
# package-lock.jsonをコミット
git add package-lock.json
git commit -m "chore: update package-lock.json"

npm ciコマンド

CI/CD環境やチーム開発では、npm installではなくnpm ciの使用が推奨されます。

1
npm ci

npm ciの特徴は以下の通りです。

npm install npm ci
package-lock.jsonを更新する package-lock.jsonを変更しない
既存のnode_modulesを保持 node_modulesを削除して再作成
バージョン範囲で最新を取得 package-lock.json通りにインストール
開発時に使用 CI/CD環境で使用

実践: プロジェクトを初期化する

ここまでの知識を活かして、実際にプロジェクトを初期化してみましょう。

ステップ1: プロジェクトの作成

1
2
3
4
5
6
# プロジェクトディレクトリを作成
mkdir express-api-demo
cd express-api-demo

# package.jsonを生成
npm init -y

ステップ2: package.jsonの編集

生成されたpackage.jsonを編集します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "name": "express-api-demo",
  "version": "0.1.0",
  "description": "Express.jsを使用したRESTful APIサーバーのデモ",
  "main": "src/index.js",
  "type": "module",
  "scripts": {
    "start": "node src/index.js",
    "dev": "node --watch src/index.js",
    "test": "node --test test/",
    "lint": "eslint src/ test/",
    "lint:fix": "eslint src/ test/ --fix"
  },
  "keywords": ["express", "api", "rest", "demo"],
  "author": "Your Name",
  "license": "MIT",
  "engines": {
    "node": ">=20.0.0",
    "npm": ">=10.0.0"
  }
}

ステップ3: 依存関係のインストール

1
2
3
4
5
# 本番依存関係
npm install express dotenv

# 開発依存関係
npm install -D eslint @eslint/js

ステップ4: ディレクトリ構造の作成

1
mkdir src test

ステップ5: エントリーポイントの作成

src/index.jsを作成します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import express from 'express';
import dotenv from 'dotenv';

dotenv.config();

const app = express();
const PORT = process.env.PORT || 3000;

app.use(express.json());

app.get('/', (req, res) => {
  res.json({ message: 'Hello, World!' });
});

app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

ステップ6: 動作確認

1
2
# 開発モードで起動
npm run dev

別のターミナルで動作確認します。

1
2
3
4
5
curl http://localhost:3000/
# {"message":"Hello, World!"}

curl http://localhost:3000/health
# {"status":"ok","timestamp":"2026-01-06T12:00:00.000Z"}

まとめ

本記事では、Node.jsプロジェクトの始め方として、以下の内容を解説しました。

  • npm initコマンドによるプロジェクト初期化方法
  • package.jsonの構造と主要フィールドの意味
  • dependenciesとdevDependenciesの使い分け
  • セマンティックバージョニングとバージョン範囲指定子
  • npmスクリプトの定義と活用方法
  • enginesフィールドによるNode.jsバージョン制約
  • package-lock.jsonの役割とnpm ciコマンド

package.jsonはNode.jsプロジェクトの心臓部です。その構造を正しく理解し、依存関係とスクリプトを適切に管理することで、保守性の高いプロジェクトを構築できます。

次回は、Node.jsの組み込みオブジェクト(process、global、Buffer)について解説します。

参考リンク