【JavaScript】package.jsonに何が書いてあるのかちょっと理解できる記事

# 書いた人について
現在フロントエンドとして働いているゆずともうします。
今回、[RUNTEQ AdventCalendar 2024](https://qiita.com/advent-calendar/2024/runteq) に参加させてもらうことになりました。
少しでも役に立つ記事作成ができれば幸いです。

# 記事概要
JavaScriptのpackage.jsonに書かれている内容について、知識を深めることができたので、初心者さんに共有できるようにまとめてみました。

# 記事の目的
JavaScriptで開発しようとすると`npm init`というコマンドを実行させられ`package.json`というファイルが生えていると思います
このファイルについて理解を深められることが目的です。

# 対象者
- JavaScriptの初学者
- package.jsonについて知りたい人
- package.jsonの書き方がよくわからない人

# npm(Node Package Manager)について
package.jsonについて理解する前に、`Node Package Manager`(以後、npmと書きます)の事を知る必要があります。

`Node Package Manager`は、JavaScriptで使われるパッケージマネージャーです。

パッケージマネージャーを使うことで、パッケージ毎の依存関係の管理を任せることができます。
パッケージマネージャーないと、手動で数多のパッケージのバージョン管理などをする必要があり、とても大変そうです。

試しに、自分の勉強用のディレクトリで使ってるaxiosというパッケージの情報を調べてみました

```terminal
// npm view {パッケージ名}で情報が表示される 一部抜粋
npm view axios
```

下記のような情報が表示されました。
`deps`の横の数字が依存しているパッケージの数で`axios`は`follow-redirects`、`form-data`、`proxy-from-env`に依存しているらしいです。

使用するaxiosのバージョンを動かすには、これらのパッケージのどのバージョン以降が必要とか決まっているみたいです。

```
axios@1.7.8 | MIT | deps: 3 | versions: 106

dependencies:
follow-redirects: ^1.15.6
form-data: ^4.0.0
proxy-from-env: ^1.1.0    

dist-tags:
latest: 1.7.8        next: 1.7.0-beta.2   old-version: 0.29.0  
```

開発していると、たくさんのパッケージをインストールして使います、それぞれ手動で管理は大変なのでパッケージマネージャーが必要と思えば良いと思います。

npmは、node.jsをインストールすると一緒にインストールされます。

node.jsのインストール方法はこの記事内では割愛します。(この記事を読んでいるので、JavaScriptのインストールはしているという前提で進めようと思います)

# package.jsonを作る
これは簡単で、node.jsのインストールされている環境で、下記のどちらかのコマンドを実行すると作ってくれます。

```terminal
npm init // 対話形式で作成
npm init -y // デフォルト値で自動生成する
```

デフォルトだとこんな感じ
```json:package.json
{
  "name": "javascript-test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}
```

# パッケージをインストールしてみる
一番大事なのはパッケージの依存関係を管理してもらうことなので、とりあえずパッケージをインストールしてみましょう。

```terminal
npm install webpack
```
インストール後にpackage.jsonをみると内容が追記されています。
```json:package.json
{
  "name": "javascript-test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": { // ← この辺が追加された
    "webpack": "^5.97.0"
  }
}
```

### devdependenciesとdependencies
パッケージをインストールすると、dependenciesという項目に追記されました。
`dependencies`は、このプロダクトを動かすときに必要なパッケージって意味です。

`devdependencies`というものもあり、こちらは開発時にだけ必要なパッケージという意味です。

### node_modules
一旦package.jsonを閉じて`npm init`を実行したディレクトリを確認すると`node_modules`という名前のディレクトリができていると思います。

npmを使ってインストールしたパッケージはこの中に入っています。

`node_modules`の中身を確認すると、沢山のディレクトリが追加されていると思います。
これは`webpack`が依存しているパッケージが多いからです。

`webpack`というディレクトリもあるはずなので、その中身をみてみましょう。

```terminal:webpack
LICENSE
README.md
SECURITY.md
bin/
hot/
lib/
module.d.ts
package.json
schemas/
types.d.ts
```
こんな感じになってます。
ここにも`package.json`があります。

これをみてみます。
`devdependencies`と`dependencie`プロパティ内にたくさんの他のパッケージが書かれているはずです。

`npm install`を行うとこれら2に書かれているパッケージとバージョンで全部インストールされます。

その結果`node_modules`配下にたくさんのディレクトリが入っているって感じです。

ただし、環境変数`NODE_ENV`をproductionにしておくと`devdependencies`はインストールされません。
基本的に実行に必要なパッケージしか必要ないためです。
```
NODE_ENV=production npm install
```

この`webpack`の例をみると`package.json`があるディレクトリの階層で`npm install`を行うと`devdependencies`と`dependencie`に記述されているパッケージがインストールされるという事が理解できます。

自分で個人開発などしている場合は`devdependencies`としてインストールしている場合は、オプションの-Dなど付けると`devdependencies`に追加できます。

```
npm install -D {パッケージ名}
```

## package.jsonの他の項目について
他の項目についても見てみましょう。
基本的には、パッケージ開発者に関係のある項目が多いです。
たくさんあるので、最低限のものだけ書いてみます。


| フィールド | 説明 | 備考 |
|:-----------|:-----|:-----|
| name | パッケージの識別子。これを指定することでinstall、importできる | パッケージの一意の識別子 |
| keywords | ライブラリの検索時に、このキーワードでカテゴライズされたものを探せる | 配列形式で複数指定可能 |
| homepage | `npm docs {ライブラリID}` or `npm home {ライブラリID}` を実行すると、指定されているURLを見に行くことができる | ドキュメントサイトなどのURL |
| repository | `npm repo {ライブラリID}` を実行すると、リポジトリを見に行ける | `owner/repo`形式または完全なURLで指定可能 |
| main | パッケージを公開する際に必須のフィールド。最初に見に行くファイルを指定できる | エントリーポイントの指定 |
| bugs | バグ報告用のURLを指定できる | `url`フィールドに報告先URLを設定 |
| files | npmのパッケージとして公開する場合に、含めたいファイルやディレクトリを指定するフィールド | 配列形式で指定 |
| engines | nodeのバージョンを指定するときに使う | `node: ">=14.0.0"`のような形式で指定 |

こんな感じです。
先ほどインストールした`webpack`を例にコマンドを実行してみましょう！

### nameを使ってインストールする
上でやったことと同じなんですが、つながりがわかりやすいかと思って、見出しを変えました。
nameの説明をみると、インストールするパッケージの識別子になっているとわかりました。
```
npm install {パッケージ名}
```

こんな風にバージョンを指定することができます。
```
npm install {パッケージ名}@{バージョン番号}

//例 webpack の バージョン5の最新版を指定
npm install webpack@5
```

どんなバージョンがあるか確認したい場合は、viewsコマンドを使います
```terminal
npm view {パッケージ名} versions

// 例 webpackの公開されているバージョン一覧
npm views webpack versions
```

webpackのpackage.jsonをみると`"watchpack": "^2.4.1"`こんな感じでバージョン指定されているものがあります。
`^`はキャロットとかハットとか呼ばれる記号で、メジャーバージョンの最新版を使うというような意味になります

この場合は`watchpack`の 2.4.1 以上 3.0.0 未満の最新バージョンをインストールするという内容になります。

### バージョン表記の見方
バージョン表記はこんな感じの意味合いみたいです。

| バージョン番号の位置 | 名称 | 意味 |
|:-----------|:-----|:-----|
| 左の数字 | メジャーバージョン | UIや機能などが大幅に変更された事を表している。破壊的な変更を含む |
| 中央の数字 | マイナーバージョン | 後方互換性を維持した機能追加や変更。基本的にはコードの修正は不要 |
| 右の数字 | パッチバージョン | バグ修正などの小さな変更 |

## 参考ドキュメントを見に行く
homepage, repository, bugsなどの項目が書かれていると、下記コマンドで対応するURLに行くことができます。

```
npm home {パッケージ名} // ドキュメントサイトなどのURL
npm repo {パッケージ名} // リポジトリのURL
npm bugs {パッケージ名} // バグ報告用のURL
```

## scriptsについて
scriptsは、プロジェクトで使うコマンドを、左辺のコマンドでショートカットとして登録できる場所です。

例えば`index.js`というJavaScriptファイルを`node.js`で実行するコマンドは
下記になります。
```
node index.js
```

これをscriptsに登録します
```
  "scripts": {
    "start": "node index.js"
    }
```

登録することで、下記のように実行できるようになります。
```
npm start
```
※ 本来は `npm run {scriptsに登録されてるコマンド}`になるのだけど、いくつかのコマンドはrunを省略できるようになっているみたいです。

この辺
```
`npm start`
`npm restart`
`npm stop` 
`npm test`
```

scriptsに関しては、自分でコマンドを作って実行してみたほうが理解しやすいかもしれません。

# まとめ
ざっくりですが、こんな感じにまとめてみました。
実際に自分でコマンドを実行しながら、ファイルをみていくと更に理解が深まると思います。
私も自分でパッケージを作ってみたりして理解を深めてみたいと思います。
プライベートでパッケージ作って見るときは`package.json`に`private: true`というプロパティを追加してうっかり公開しないように注意してください。

# 参考

https://developer.mozilla.org/ja/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management

https://www.hitachi-solutions.co.jp/sbom/blog/2023033101/

https://www.udemy.com/share/107wK13@NRUnz3RTzFTEX606l_6i71jPRXFc12VOknV09ULgDBlvcZ3wd1x7SQSXrDmH0-ov/