重い腰を上げて、NPMの取りこぼしを回収する

[zennからの転載です。](https://zenn.dev/hedrall/articles/251441f391990f)

# 概要

`npm` をなんとなく使って来ましたが、実は色々と機能が豊富なので、この期に取りこぼしを回収するべく少し調べてみました。取りこぼしそうな部分をまとめたいと思います。

# npmとは

Node.jsのパッケージ管理ツール。自身もJSで記述されており、Node.jsのリリースに含まれています。
2020年にGithubが買収されています。
日本人で一番コミットが多いのが[watildeさん](https://github.com/watilde)の様です。

# lockファイルの優先順位

1. `npm-shrinkwrap.json`
2. `package-lock.json`
3. `yarn.lock`

# npmコマンド

[公式](https://docs.npmjs.com/cli/v7/commands)を見ると意外にたくさんコマンドがあります。

## パッケージの管理系

### `npm audit`

実行すると、脆弱性が報告されているパッケージ・バージョンをレポートしてくれる。脆弱性が発見された場合は`npm audit fix`で自動修正できる場合がある。自動修正されない場合は手動で修正する必要がある。

### `npm ci`

CI環境などで使用する `npm i`。pcakage-lock.jsonがあって、node_modulesがない時に早いらしい。
試しに私のプロジェクトで実行したところ(ざっくりです)、
npm i ⇒ 7.8
npm ci ⇒ 7.0

あまり変わらない印象。ただCIを高速化したいのであれば、`yarn`やら[`pnpm`](https://github.com/pnpm/pnpm)を使うのも手だが、安全の為にnpmにだけ依存する選択もありうる。

### `npm dedupe`

複数のパッケージが必要とするパッケージをそれぞれの配下でインストールするのでなく、必要とする全てのパッケージが参照できる位置までディレクトリ構造を遡って配置する。

```
node_modules/A/node_modules/C
node_modules/B/node_modules/C
=>node_moudles/C
```

現在は `npm i`を実行すると自然とdedepeしてくれる様子。試しに`npm ls --depth=3`を実行すると、dedeupedの文字が散見されるはず。

`npm find-dupes` は `npm dedupe --dry-run` と同じ

### `npm prune`

package.jsonに記載されていないパッケージをnode_modulesから削除する。

`npm prune --prodution`を実行すると、`devDependancy`に記載されているパッケージもnode_modulesから削除される為、ビルドする時に便利です。

### ブラウザでパッケージの関連ページを開く便利系

打ってみて何が開くか確かめてください。
`npm repo`
`npm home`
`npm docs`
`npm bugs`

## パッケージの実行系

### `npm exec`

基本npxと同じ動作。[npx内部で `npm exec` をcallしている様に見える。](https://github.com/npm/cli/blob/dedb9c8f8b0891b30aa76e60cdb1c4f0f9b2f22f/bin/npx-cli.js#L6-L7)

違いは引数の渡し方。`npx` と違い `--` を使って渡す。

### `npm explore`

別プロセスで指定したパッケージ配下を開く。

```bash
# イメージ
$ npm i axios
$ npm explore axios
bash$ pwd
# => /path/to/node_modules/axios
exit;

## パラメータを指定するとただちに終了
npm explore axios -- git pull origin master
```

## インストール状況の確認系

### `npm ls`, (`npm ll`, `npm la`は出力が微妙に違う)

デフォでは1階層しか見えないので、 `npm ls --all` とか `npm ls --depth=3`とかすると深く見れる。v8で大幅な変更を予定している。

> `npm explain` との違いはなんだろう？

### `npm outdated`

更新のあるライブラリを一覧する。

ex)
```bash
$ npm outdated
Package                      Current    Wanted    Latest  Location                                 Depended by
@babel/core                  7.13.10   7.13.14   7.13.14  node_modules/@babel/core                 my-project
@babel/preset-env            7.13.10   7.13.12   7.13.12  node_modules/@babel/preset-env           my-project
...
```

Current, Latestはわかると思いますが、Wantedはpackage.jsonの設定で許容される最新のバージョンです。

赤い出力はcurrent < watedなので、すぐにアップデートすることが推奨されるパッケージです。

## パッケージの探索系

### `npm search`

パッケージを文字列一致で検索する。 ex) `npm search react`

正気表現も使える。 ex) `npm search /react-.*/`

### `npm versions パッケージ名`  

バージョン一覧がみられる

### `new view パッケージ名`

npmパッケージの詳細を確認する

## NPMの設定系

### `npm root`

インストールされるnode_modulesの位置を参照する。 `npm prefix -g`でグローバルの参照先を見る。

`npm prefix (-g)`はプロジェクトのパスを出力し、

`npm bin (-g)`は実行ファイルのパスを出力する。

## package.jsonの管理系

### `npm install`, `npm uninstall`, `npm update`

省略

### `npm set-script`

npmスクリプトを追加する。
ex) `npm set-script hoge 'npm run other command'`

## その他

### `npm hook`

npmレジストリの変更をweb hookで通知を受けることができます。受け取るのにはサーバを立てる必要があ理ます。

実装の参考: [https://github.com/npm/npm-hook-slack](https://github.com/npm/npm-hook-slack)

### `npm link`

ローカルで開発中の別レポをnode_modulesにインストールしたかのようにリンクさせる。

リンク元で、 `npm link` を実行するとグローバルにリンクが作成され、使用するプロジェクトで `npm link パッケージ名`すると、node_modulesの中にシンボリックリンクが生成される。

### `npm shrinkwrap`

`npm-shrinkwrap.json`を生成する。npm-shirinkwrap.jsonは `npm i`の時に `package-lock.json`

より優先的に読み込まれます。
通常は `package-lock.json` を使用する為、あまり使用しないと思います。

## NPMパッケージの開発者向け

`npm publish`

npmパッケージを公開する

など

# package.json

## `main`

最初に読まれるファイル。 `axios`の `main`は `index.js`なので、 `require('axios')`すると `node_modules/axios/index.js`が読み込まれる。

## `browser`
クライアントサイド(ブラウザ)で使用することが想定されるパッケージの場合、`main`ではなく、`browser`にセットする。

## `bin`
CLIツールの場合は`bin`に実行ファイルを指定する。コマンド名をつけることも可能。指定した名前で`node_modules/.bin`に保存される

```json
{
  "bin": {
    "myapp": "./cli.js"
  }
}
```

# GUIツール

[q-nick/npm-gui](https://github.com/q-nick/npm-gui)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194978/a5764586-e3c7-f775-5ec6-439be25a3751.png)

[720kb/ndm](https://github.com/720kb/ndm)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194978/0e13741f-f31c-bba2-07b0-3b336d2a0738.png)


どちらもパッケージの追加や、outdatedなパッケージの更新ができる模様ですが、npm scriptを実行したりと言う様な機能は無い模様。

# 参考

- [公式サイト](https://docs.npmjs.com/cli/v7/commands)
- [全部知ってる？ npmを使いこなすために絶対知っておきたい10のこと](https://www.webprofessional.jp/10-npm-tips-and-tricks/)
- [便利なnpmコマンド | スペースマーケットブログ](https://blog.spacemarket.com/code/npm-command/)
- [package.jsonの中身を理解する - Qiita](https://qiita.com/dondoko-susumu/items/cf252bd6494412ed7847)