そろそろ適当に npm install するのを卒業する
はじめに
ネットに転がっている記事などで npm install
のコマンドをよく分からず実行してきましたが、そろそろその状態から卒業したかったので備忘録をかねてこちらの記事を投稿しました。
npm install
コマンドに関することをメインにお伝えしますが、package.json や node_modules など npm を語る上で基本的なことについても触れていきたいと思います。
目的
この記事の目的は、以下の4つの npm install
コマンドを実行したときの挙動の理解と、これら4つのコマンドを必要な状況に応じて使いわけるようになることです。
npm install
npm install -g <package>
npm install <package>
npm install -D <package>
つまり、適当に npm install
するのを卒業することです。
動作環境
# Node.js のバージョン確認
$ node -v
v14.13.1
# npm のバージョン確認
$ npm -v
6.14.8
ちなみに npm 自体のアップデートは以下のコマンドになります。
npm はメジャーバージョンが異なるとかなり挙動が異なるので、参照する記事の npm のバージョンにも注意が必要です。
# npm のアップデート
$ npm update -g npm
npm install を説明する前に知っておきたいこと
この辺を理解しておかないと適当に npm install
してしまうことになるので、先に説明します。
知っている方は飛ばしても大丈夫です。
Node.js
Node.js とはサーバサイドで動く JavaScript のことです。
npm
npm(Node Package Manager)とは Node.js のパッケージ(Package)を管理する(Manager)ツールです。
Node.js のパッケージ(Package)とは予め用意された便利な機能(各種フレームワークやライブラリ)をまとめたものです。
yarn
yarn とは 2016 年にリリースされた npm と互換性のあるパッケージマネージャーです。
今回は yarn コマンドについては触れませんが、以下の意見にとても納得しました。
ご参考まで。
ちなみに: 似たような CLI として Facebook が開発した Yarn がある。これは npm の色々な欠点(スピードなど)を補うように作られたものであり、かなり人気がある。npm パッケージの README でしばしば npm と yarn でインストールする方法が両方書かれていたり、時には「yarn を使用することを推奨する」と書かれていたりする。しかし、npm も改善されてきており、わざわざ yarn をインストールして使用するメリットはあまりないと筆者は考えている。特に初心者にとっては、スタンダードでないツールを使用すると無駄に学ぶことが増えるのでおすすめしない。
【初心者向け】NPMとpackage.jsonを概念的に理解する (抜粋)
https://qiita.com/righteous/items/e5448cb2e7e11ab7d477
package.json
package.json とは Node.js ベースの JavaScript アプリ開発において、自身のパッケージ(= プロジェクトそのもの)を管理するために使われるファイルのことです。
npm init
とコマンド実行すると package.json が作成されます。
package-lock.json
簡単に説明すると package.json を用いてパッケージをインストールした結果が記載されるファイルです。
今回は説明を省略しますが、詳しく知りたい人は【参考】のリンク先を参照してください。
npm init
package.json は普通に touch コマンドなどでも作成できますが、基本的には npm init
とコマンド実行して package.json を作成します。
(【脱線】npm init しないとどうなる?)
# 何もない空のディレクトリ
$ ls
(標準出力なし)
# npm init による package.json の作成(質問をされるが一旦すべて Enter で通過する = npm init -y コマンド実行時と同じ挙動)
$ npm init
# package.json が作成されている
$ ls
package.json
package.json の初期値は以下のようなものになります。
{
"name": "<current directory name>",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
package.json にはいろいろ項目がありますが name
, version
, description
, keywords
, author
, license
などのデータは単なる自身のパッケージ(= プロジェクトそのもの)のメタデータであり、自身のパッケージ(= プロジェクトそのもの)を公開しなのであれば、気にする必要はありません。
dependencies
, devDependencies
, scripts
, config
の4つぐらいを抑えれば、あとは必要に応じて調べて設定すれば問題ないかと思います。
【参考】
package.jsonの構造
npm と package.json の関係
公開されているパッケージ(ライブラリやフレームワークなど)は npm
コマンドによってインストールすることができます。
package.json が存在するディレクトリで npm
コマンドによってパッケージをインストールすると、自動的に package.json が更新されます。
また、人間が package.json に記述されているパッケージ名やバージョン情報を直接編集することはありません。
それらは npm
コマンド経由で更新します。(大事)
node_modules
node_modules とは package.json を元にしてインストールされる各種パッケージがインストールされるディレクトリ先のことです。
package.json さえあれば、npm install
コマンドの実行によって node_modules が生成することが可能です。
そのため通常は .gitignore
に指定されるディレクトリになります。
npm install
ここからがこの記事の本題になります。
パッケージを node_modules にインストールするには npm install
とコマンド実行します。
この npm install
というコマンドですが、これがいろいろと種類があってややこしいので詳しく説明していきます。
とりあえずよく使うコマンド一覧
引数なしでの実行する場合
# 引数なし実行(package.json のあるディレクトリで実行する)
npm install
グローバルインストール
# グローバルインストール
npm install -g <package>
npm install --global <package>
ローカルインストール
# ローカルインストール
# package.json の dependencies に追加するとき(npm v4 以下では --save (= -S) のオプションが必要、npm v5 以上ではデフォルトになったため不要)
npm install <package>
npm install --save <package> # デフォルトで入っているオプションなので使う必要なし
npm install -S <package> # デフォルトで入っているオプションなので使う必要なし
# package.json の devDependencies に追加するとき --save-dev (= -D)
npm install --save-dev <package>
npm install -D <package>
バージョン指定のインストール
# バージョンに関する指定
npm install <package>@x.y.z # バージョンを指定する場合
npm install <package>@latest # 最新版を指定する場合( @latest とつけなくても指定しなければ最新版がインストールされる)
npm install
引数なし 引数のない npm install
コマンド実行時の挙動は、引数のある npm install <package>
とわけて考えたほうがわかりやすいです。
引数のない npm install
コマンド実行をすると、カレントディレクトリにある package.json に記述されている情報を元に、そこに記述されている パッケージを node_modules (インストール先)にインストールします。
使うタイミングは 「package.json を共有されて node_modules を作成していない時」や「package.json が更新された時」などになります。
また、npm install
コマンド実行する前に、あらかじめ package.json にインストールしたいパッケージ情報を記述しておく必要があります。
そして、その package.json へのパッケージ情報を記述は、引数ありの npm install <package>
のコマンドの実行によって行います。
npm install <package>
引数あり 大きな分類としてグローバルインストールとローカルインストールに分けられます。
また、ローカルインストールのなかでも package.json の記述先の違いで2つに分けられます。
全体で見るとグローバルインストール1種類、ローカルインストール2種類の合計3種類になります。
コマンド | 大分類 | package.json の記述先 |
---|---|---|
npm install -g <package> |
グローバルインストール | - |
npm install <package> |
ローカルインストール | dependencies |
npm install -D <package> |
ローカルインストール | devDependencies |
ちなみに「グローバルインストール」と「ローカルインストール」の両方とも自身のPCの環境へインストールされます。
グローバルインストール
グローバルインストールすると自身の PC の環境ならどこでもインストールしたパッケージ(コマンド)が実行できます。
ただし、グローバルインストールしても nodebrew
などで複数の Node.js のバージョンを管理している場合は、それぞれのバージョンで npm install -g <package>
したパッケージが、それぞれ別のものとして管理されるので注意が必要です。
【参考】
【npm】 パッケージのインストール先の確認(npm list)
グローバルインストールの挙動
# 未インストールなので cowsay コマンドは実行できない
$ cowsay "hoge"
zsh: command not found: cowsay
# cowsay コマンドをグローバルインストール
$ npm install -g cowsay
$ cowsay "hoge"
______
< hoge >
------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
ローカルインストール
ローカルインストールすると node_modules と同じディレクトリにある場合にパッケージ(コマンド)が実行できます。
【参考】
npm でローカルインストールしたパッケージを CLI でコマンド実行する方法(npm-srcipts, npx)
-D
オプションなしの場合)
ローカルインストールの挙動( # 適当なパッケージ(cowsay)をインストール
$ npm install cowsay
+ cowsay@1.4.0
# dependencies の項目に cowsay が追加されていることが確認できる
$ cat package.json
{
(省略)
+ "dependencies": {
+ "cowsay": "^1.4.0"
+ },
(省略)
}
# node_modules にインストールされるのでパスを通しながら実行可能
$ ./node_modules/.bin/cowsay "hoge"
______
< hoge >
------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
-D
オプションありの場合)
ローカルインストールの挙動( # 適当なパッケージ(typescript)を -D のオプションをつけてインストール
$ npm install -D typescript
+ typescript@4.0.3
# devDependencies の項目の typescript が追加されていることが確認できる
$ cat package.json
{
(省略)
"dependencies": {
"cowsay": "^1.4.0"
},
+ "devDependencies": {
+ "typescript": "^4.0.3"
+ },
(省略)
}
# -D のオプションをつけても変わらずに node_modules にインストールされるのでパスを通しながら実行可能
$ ./node_modules/.bin/tsc --version
Version 4.0.3
グローバルインストール と ローカルインストールの使い分け
では、パッケージをインストールする場合、グローバルインストール と ローカルインストール のどちらにインストールすべきでしょうか?
状況によりますが、闇雲にグローバルインストールするのは避けたほうがいいです。
グローバルインストールされたパッケージは環境が異なると使用することができません。
例えば、PC を買い替えたらそのパッケージを使用することができないですし、他人の PC でもそのパッケージを使用することができません。
そいういうときにローカルインストールで作成される package.json だけを共有すれば、どの環境でも npm install
を実行するだけで、同じパッケージを使用することができます。
『どんなディレクトリでも、いつでもどこでもそのコマンドを使いたい』というパッケージだけをグローバルインストールして、それ以外はローカルインストールするのが無難だと思います。
-D
オプションをつけるべきケース
ローカルインストール時に 一般的に、開発環境でしか使用しないパッケージについては npm install -D <package>
として、そうではないパッケージについては npm install <package>
とします。
パッケージ名の引数をとらない npm install
には --production
とオプションをつけることで、npm install -D <package>
でインストールしたパッケージを除いて node_modules にインストールすることができます。
このように --production
のオプションをつけることによって開発環境でしか使わないパッケージを除外できるので、本番環境デプロイ時に参照されることのないパッケージをインストールしなくて済むようになります。
ローカルインストール時の -D
オプションの有無による違いをまとめると以下のようになります。
実行するコマンド | package.json の記述先 | それぞれの使い分け |
---|---|---|
npm install <package> |
dependencies |
開発環境以外でも使用されるパッケージ ex) express |
npm install -D <package> |
devDependencies |
開発環境のみで使用されるパッケージ ex) eslint |
また、パッケージ名の引数をとらない npm install
実行時の --production
オプションの有無による違いをまとめると以下のようになります。
実行するコマンド | インストール対象 | 実行するタイミング |
---|---|---|
npm install |
・ dependencies ・ devDependencies
|
開発環境 |
npm install --production |
・ dependencies のみ |
本番環境など開発環境でしか使われないパッケージをインストールしたくないとき |
いろいろ書いていますが、ケースバイケースなので、実際に npm install --production
をするときになってから考えればいいと思います。
【参考】
【package.json】dependencies, devDependencies の使い分けを考える
まとめ
それぞれの npm install
コマンドの使用するタイミングをまとめると以下になります。
コマンド | 使用するタイミング |
---|---|
npm install |
新規 or 更新された package.json を元に node_modules を作成するとき |
npm install -g <package> |
グローバルインストールするとき(= どんなディレクトリでもそのコマンドを使えるようにしたいとき) |
npm install <package> |
package.json にローカルインストールしたい(= そのディレクトリだけで使用できるようにしたい)パッケージを追加するとき(本番環境でも使用するパッケージ) |
npm install -D <package> |
package.json にローカルインストールしたい(= そのディレクトリだけで使用できるようにしたい)パッケージを追加するとき(開発環境でのみ使用するパッケージ) |
さいごに
いかがだったでしょうか?
もうこれで、以下の4つの npm install
コマンドは使い分けできると思います。
npm install
npm install -g <package>
npm install <package>
npm install -D <package>
ここには入りきらなかった npm に関する記事たちのURLを貼っておきます↓
Node.js のバージョン管理についてのメモ(nodebrew, nodenv)
【npm】 パッケージのインストール先の確認(npm list)
セマンティック バージョングについてのメモ
package.json に記述される チルダ ^ や キャレット ~ について
package-lock.json ってなに?
npm init しないとどうなる?
npm でローカルインストールしたパッケージを CLI でコマンド実行する方法(npm-srcipts, npx)
npx でパッケージ名とコマンドが異なる場合(npx -p <package> -c "<commond>"
)
npm-scripts の pre, post プレフィックス
npm-scripts の 順次・並列実行(npm-run-all)
package.json に記載されているパッケージのバージョンアップ方法【npm-check-updates, outdated】
package.json の config の使い方について
Discussion