パッケージ管理ツール「npm」を初学者が理解するまでの過程を記録

先日Laravelを導入して、過去にPHPフルスクラッチで作ったサービスをLaravelに移行した。

cssやjs、vue.jsをlaravelで使用する際、その過程で「パッケージ管理ツールのnpm」が登場したが、正直「何のパッケージを管理するの？」「そもそも管理って何をどう管理するの？」「一体何のメリットがあるの？」と意味不明だった。

そこで今回、パッケージ管理ツールである「npm」について、ちゃんと理解したかったので本腰入れて勉強してみた。

この記事はその過程を記録したものです。

※随時更新です。間違った理解がある場合はどうかご指摘お願いします。


##npmとは
一言で言うと、npmはnode.jsの「パッケージ」を管理するツールのことを指すとのこと。
正式名称は「Node Package Manager」

名前の通りだが、 当然分からない。ここでさっそく疑問が２つ。

nodo.jsとパッケージという言葉だ。

###node.jsって何？

node.jsは何かというと、サーバーサイドでjavascriptを実行できるようにしてくれるプラットフォームのような物。

TECHACADEMYに分かりやすい表現がったので引用。

「Node.jsとは、サーバーサイドのJavaScript実行環境」
 引用元： https://techacademy.jp/magazine/16248?yclid=YJAD.1587373943.WSKMnDqdcq3uCZO6.oygqWCC0Ws2gflK.jOXchfBL6lRF9Rbg87Y_QWETDo8smtvBUXgvj6JBOAzga4-

そもそもjavascriptってブラウザ上で動作する（例えばドロップダウンメニューとか画像スライド、文字数カウント）言語のはずだったけど、サーバサイドでjavascriptを実行できるって言われても全くピントこない。

勝手なイメージだけど、ユーザーが入力したデータ等をDBへ保存したり、データを取得して画面へ出力するといったサーバーサイドの動作をjavascriptで記述できるみたいな感じだろうか。


サーバーサイドであれば、PHPとかRubyがあるからそれでいいじゃんと思ったけど、どうやら開発するWEBサービスによってはPHPやRubyよりもnodo.jsを使いjavascriptで開発した方が適しているらしい。

なぜならnodo.jsで開発を行うと、メモリ消費量が少なく、同時に大量のトラフィックを捌くことができるらしい。

LINEやTwitter、FaceBookといったリアルタイム型のチャットサービスの開発や、ゲームの開発でnodo.jsを使うと通信速度も一定の速度を保ちやすく、リアルタイムでのデータ更新の監視などを簡単にできるので、そういった開発で使われることが多いと書いてあった。

ちなみに、node.jsはプロントサイドの開発担当者が「バックエンドでもjavascriptが使えたら便利だよね。」という考えで生まれたらしいが、現状では、フロントサイドのjavascriptとは全くの別物で、互換性もない。

奥が深すぎて初学者の私には分からないが、つまるところnodo.jsも、より良いWEBサービスを開発するために生まれた言語の一種なのだと、とりあえず理解しておく。


###nodo.jsのパッケージって何者？

nodo.jsのパッケージとは、予め用意された便利な機能をまとめたものらしい。

パッケージと言えば、普通に考えれば入れ物である。

例えば、旅行でハワイに行こうと思った場合、航空券やホテルや食事などが全て一つの商品（パッケージ）で販売されている。
消費者は自分にあった旅行パッケージを選ぶだけ。

これと同じイメージなのだろう。

nodo.jsのパッケージの一つに「gulp」というパッケージがあるが、調べたところ、cssファイルの圧縮や画像ファイルの圧縮といった便利な機能を一つにまとめたタスク管理のパッケージらしい。

使い方はまだ分からないが、確かにそういったWEB開発で必要なタスクを実行できるファイルをパッケージとして一つにまとめてくれていれば、自身の開発環境にそのパッケージをインストールするだけで、開発環境の構築が簡単にできるとう点は想像がつく。

ちなみこれらのnodo.jsのパッケージは、nmpでインストールする際に使えるとの事。

早速、「gulp」パッケージをインストールしてみる事にした。


##npmでパッケージ「gulp」をインストールしてみた

※laravelを導入する時に、npmを使えるようにしてあったので、ここではnpmのインストール方法は割愛する。

まず、デスクトップにsampleというフォルダを作成

勉強のためにターミナルのコマンドでやってみる。

```
$ cd ~/Desktop //デスクトップへ移動
$ mkdir sample //sampleフォルダを作成
```
中身は当然空である。

<img width="820" alt="スクリーンショット 2020-04-20 19.21.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518144/4d198594-562f-bc57-a4b2-4a39debc6523.png">

このsampleフォルダが、WEBサービスを開発する開発環境だと仮定して操作してみる。

まず、開発環境でnpmを使う場合は、そのフォルダ内でnpmを使うことを宣言する必要があるらしい。

作成したsampleフォルダに移動し、宣言してみる。

```
$ cd sample //sampleフォルダへ移動
$ npm init //npmを使うと宣言
```

npm initを実行すると、ターミナル上で色々な質問をされるが、調べたところとりあえず何も入力せずにEnterを押していけばいいらしい。

Enterを押していくと「Is this OK? (yes)」と表示されるのでyesかEnterキーを押す。

なんとなくカッコいいので「yes」と入力してみた笑

<img width="452" alt="スクリーンショット 2020-04-20 19.28.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518144/3f3ccddc-1637-6742-0cc0-7c8a799326c2.png">

入力しても何も起こらなかったのでおかいいと思ったが、sampleフォルダ内に「package.json」というファイルが作成されていた。

<img width="748" alt="スクリーンショット 2020-04-20 19.31.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518144/5c527c15-6592-73a8-8691-cc748a8aa33e.png">

package.jsonのファイルの中身はこんな感じ。

```json:package.json
{
  "name": "sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
```
なるほど。先ほどEnterキーですっ飛ばしてきた色々な設定がpackage.jsonで表示されている。
packageの名前とか決められるらしい。

そうなると、このファイルがnpmでインストールするnodo.jsのパッケージ情報を記録するためのファイルなのだろう。

早速、npmでパッケージ「gulp」をインストールしてみる。

```
$ npm install gulp
```

<img width="591" alt="スクリーンショット 2020-04-20 19.41.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518144/d611ef99-9acd-65dc-dd96-40b0f0cdb09e.png">

赤い線で囲ってあるように、gulp@4.0.2がインストールされた。

sampleフォルダの中身はこんな感じ。
<img width="781" alt="スクリーンショット 2020-04-20 19.46.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518144/63fbbd8e-dd13-3e53-8930-48f79ccbd439.png">

新たに「node_modules」というフォルダと「package-lock.json」というファイルが追加された。

先ほどのpackage.jsonはどうなったかというと

```json:package.json
{
  "name": "sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",

  //　↓npm install gulpで新しく出現した文言 
  "dependencies": {
    "gulp": "^4.0.2"
  }
}
```

新しく"dependencies"という配列名で、"gulp" : "^4.0.2"が追加になっている。

つまりこのpackage.jsonファイルを見ることで、自分が開発環境にインストールしたパッケージの「名前」とその「バージョン」が分かると言うことだ。

なるほど、パッケージ管理と言うのはこのことか。確かに自分が何のパッケージをインストールして、しかもそのバージョンがどのバージョンなのかいちいち覚えてられないと思う。

インストールすると同時にpackage.jsonに記録してくれるので、多分かなりありがたい存在。

これを他の開発メンバーに見せるだけで、開発環境のインストールしているパッケージ情報が分かる。


ちなみにlaravelを導入した際も、このpackage.jsonが勝手に作成されていたので中身を見てみた。


```json:laravel(ver5.8.37)プロジェクト内のpackage.json
{
    "private": true,
    "scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "npm run development -- --watch",
        "watch-poll": "npm run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "devDependencies": {
        "axios": "^0.19",
        "bootstrap": "^4.1.0",
        "cross-env": "^5.1",
        "jquery": "^3.2",
        "laravel-mix": "^4.0.7",
        "lodash": "^4.17.13",
        "popper.js": "^1.12",
        "resolve-url-loader": "^2.3.1",
        "sass": "^1.15.2",
        "sass-loader": "^7.1.0",
        "vue": "^2.5.17",
        "vue-template-compiler": "^2.6.11"
    }
}

```

若干ファイルの中身は違うものの、「devDependencies」という名前でパッケージ情報が載っていた。

調べてみたが「devDependencies」は開発環境時のみ使うパッケージの集まりで、「dependencies」は実際にWEBサービスとしてリリースした際の実行環境においても使うパッケージの集まり。

このpackage.jsonを見ることで、laravel導入時に開発環境に必要なパッケージ情報が確認できる訳だ。

よくみるとjqueryも登録されている。jqueryはjavascriptのライブラリだったと思うが、どうやらnpmではライブラリ情報も管理してくれるらしい。

jqueryをインストールするには下記のコマンドを入力すればインストールする事ができる。

```
$ npm install jquery
```

ためしに、先ほどデスクトップに作ったsampleフォルダでインストールしてみる。

```json:package.json
{
  "name": "sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "gulp": "^4.0.2",
    "jquery": "^3.5.0"　//新しく追加された
  }
}
```

jqueryなどのライブラリもnpmで管理できることが分かった。


ちなみにnmpのインストールコマンドは、様々なオプションが付けられるらしい。



##インストールのオプション

```
//　通常
$ npm install パッケージ名

//　-g （PC全体で使えるようになる）
$ npm install -g パッケージ名

// --save （package.jsonに記録する場合）
$ npm install --save パッケージ名

// --save-dev （開発時にしか使わないツールをインストールする際に使用）
$ npm install --save-dev パッケージ名


// バージョンを指定してインストールする場合
$ npm install --save-dev パッケージ名@0.3.17
```

オプションで--saveと付けると、実際にインストールするのではなく、package.jsonにインストールするパッケージ情報を保存する事ができる。

さらに--save-devと付けると、開発時のみに使用する"devDependencies"に登録されるらしい。

やってみた。今回はvue.jsを使うためのvueライブラリをpackage.jsonへ保存してみる。

```
$ npm install -save-dev vue
```

結果がこちら。

```json:package.json
{
  "name": "sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "gulp": "^4.0.2",
    "jquery": "^3.5.0"
  },

  //--save-devを付けてinstallコマンドを実行
  "devDependencies": {
    "vue": "^2.6.11"
  }
}

```

確かに保存されている。

ちなみにこの状態から、vueライブライを実際にインストールしたい場合は下記のコマンドを入力すれば可能。

```
$ npm install
```

上記のコマンドを入力するとsampleフォルダ内にあるnodo_modulesというフォルダ内にvewファイルが作成されていた。

<img width="781" alt="スクリーンショット 2020-04-20 21.55.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518144/eb2435be-fbed-47e7-2f5e-4493ab2caf9f.png">



##npmの非常に大きなメリット

自分の開発環境を他の人に簡単にコピーできる。

例えば、今までsampleフォルダを作って、gulpやjquery,vueといったパッケージやライブラリをインストールしてきた。

もし仮にこの環境を他の人にも渡したい場合、npmを使うと実は簡単に出来てしまうらしい。

方法は単純で、下記の手順で可能。
①package.jsonを、新たに開発環境を構築したい渡す
②コマンド：npm installでpackage.jsonに登録されたパッケージをインストール


試しにやってみた。

```
//デスクトップへ移動
$ cd ~/Desktop 

//sample_copyフォルダを作成
$ mkdir sample_copy

//sample_copyフォルダへ移動
$ cd sample_copy

//sampleフォルダのpackage.jsonをコピー
$ cp ../sample/package.json package.json
```

※sample_copyが、sampleと同じ開発環境を構築したいフォルダ

ここまでやると、フォルダ内はpackage.jsonのみ存在している。

<img width="781" alt="スクリーンショット 2020-04-20 22.12.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518144/a5173a70-d997-ea1b-01bd-02078b9f6217.png">

この状態から

```
$npm install
```
を実行してみると、中身がsampleフォルダと同じになった。

<img width="781" alt="スクリーンショット 2020-04-20 22.15.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518144/ff3cebf4-2de4-589f-2c1f-c8c15f6958ed.png">

node_modulesの中に、ちゃんと「gulp」「jquery」「vue」といった今回インストールしたパッケージが含まれていたので、無事sampleと同じ環境を構築出来たことになる。

##まとめ

こんな感じで色々とnpmを使う事でなんとなくのメリットが見えてきたのでまとめておく。

【メリット】
①npmにより開発環境に必要なnodo.jsのパッケージだったりライブラリをコマンド１行でインストールできる
②さらにインストールしたパッケージのバージョンが自動的に保存される
③バージョンが保存されているので、仮にパッケージがバージョンアップしたとしても、保存したバージョンをインストールすればバージョンの更新によるバグは起きない
④インストール時にオプションを指定することで、パッケージを使う環境を開発環境のみに指定することも可能
⑤他の人に同じパッケージ環境を構築する際はpackage.jsonを渡すだけで可能

とりあえず半日色々と試しまくり調べまくり、npmはかなり便利という事が分かった。