yarn xxxxしたらgyp ERRが出たときの対処法

## はじめに
Qiita初投稿です。緊張。
渋谷の事業会社でしがないフロントエンドエンジニアをやっています。

## なぜgyp ERRに出会ってしまったか①
弊社のフロントエンドグループでは現在、レガシーな開発環境を脱却し、当たり前に品質を担保できる環境づくりを行っています。
その一環として、**みんな大好きESLint**を導入しようと企みました。

インストールコマンドを打って、 `.eslintrc`をちょちょっと作成したら導入完了でしょ＼(^o^)／とか思って

```
yarn add -D eslint
```

を実行したら

```
$ yarn add -D eslint
yarn add v1.15.2
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
warning Pattern ["glob@latest"] is trying to unpack in the same destination "~/node_modules/glob" as pattern ["glob@^7.1.3","glob@^7.1.0","glob@^7.1.3"]. This could result in non-deterministic behavior, skipping.
error eslint@5.16.0: The engine "node" is incompatible with this module. Expected version "^6.14.0 || ^8.10.0 || >=9.10.0". Got "8.9.4"
error Found incompatible module
```

見事にエラーが出ました。

```
error eslint@5.16.0: The engine "node" is incompatible with this module. Expected version "^6.14.0 || ^8.10.0 || >=9.10.0". Got "8.9.4"
```

弊プロダクトでは、Node.jsの`v8.9.4`を使用しているのですが、ESLint推奨のNode.jsのバージョンと合っていないらしいです。
`v9.10.0`以上であれば良さそうなので、**Node.jsを最新のLTSにアップデート**することになりました。

（ついでに[Node.jsのリリースノート](https://nodejs.org/ja/about/releases/)を眺めていたら、`v8`は2019年いっぱいで`End-of-Life`らしいのでちょうどよかったです）

## なぜgyp ERRに出会ってしまったか②
前段でNode.jsのアップデートをすることになったので、せっせと調査をはじめました。

弊プロダクトではNodeのバージョン管理ツールとして[nvm](https://github.com/nvm-sh/nvm)を使用していて、
`.nvmrc`を1行変更すれば終了ということがわかりました（ラッキー）。

いざ`.nvmrc`を`v10.15.3`（2019/5/9時点でのLTS最新版）に編集して`yarn install`を実行すると

```
$ yarn install

~~~略~~~

warning Error running install script for optional dependency: "~/node_modules/utf-8-validate: Command failed.
Exit code: 1
Command: node-gyp rebuild
Arguments: 
Directory: ~/node_modules/utf-8-validate
Output:

~~~略~~~

5 warnings and 1 error generated.
make: *** [Release/obj.target/validation/src/validation.o] Error 1
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (~/node_modules/node-gyp/lib/build.js:262:23)
gyp ERR! stack     at ChildProcess.emit (events.js:189:13)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:248:12)
gyp ERR! System Darwin 18.5.0
gyp ERR! command \"~/.nvm/versions/node/v10.15.3/bin/node\" \"~/node_modules/.bin/node-gyp\" \"rebuild\"
gyp ERR! cwd ~/node_modules/utf-8-validate
```

**gyp ERR**に出会いました。
`.nvmrc`を1行変更すれば終了！なんて都合のいい話はないですね。

## エラーの原因
**gyp ERR**とはなんらかのモジュールがNode.jsのバージョンに合っていない場合に起こるエラーのようです。
（エラーの詳細は調べていないので、気になる方は調べてみてください。教えていただけるとさらに嬉しいです）

今回は`Command failed.`となっている`utf-8-validate`というモジュールが原因のようなので、そこから探っていきます。

package.jsonのdependenciesには記載のないモジュールのため、**使用しているなんらかのモジュールが依存しているモジュール**であることがわかります。

その**なんらかのモジュール**を特定するのに使うのが、[yarn why](https://yarnpkg.com/en/docs/cli/why)コマンドです。

## yarn why
`yarn why`コマンドは、**引数に渡したモジュールがどのモジュールに依存しているかを明らかにするコマンド**です。
package.jsonに記載のあるモジュールにたどり着くまで`yarn why xxxx`を繰り返します。

```
$ yarn why utf-8-validate
yarn why v1.15.2
[1/4] 🤔  Why do we have the module "utf-8-validate"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] 🔍  Finding dependency...
[4/4] 🚡  Calculating file sizes...
=> Found "utf-8-validate@1.2.2"
info Reasons this module exists
   - "_project_#ws" depends on it
   - Hoisted from "_project_#ws#utf-8-validate"
```
`utf-8-validate`は`ws`というモジュールで使用されていることがわかります。

```
$ yarn why ws
yarn why v1.15.2
[1/4] 🤔  Why do we have the module "ws"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] 🔍  Finding dependency...
[4/4] 🚡  Calculating file sizes...
=> Found "ws@0.8.0"
info Has been hoisted to "ws"
info Reasons this module exists
   - "workspace-aggregator-4046ff3c-1c25-4458-aaf7-3f9e6df87138" depends on it
   - Hoisted from "_project_#hoge#sc5-styleguide#socket.io#engine.io#ws"
   - Hoisted from "_project_#hoge#sc5-styleguide#socket.io#socket.io-client#engine.io-client#ws"
```

`ws`は`hoge`ディレクトリ内で使用されている`sc5-styleguide`というモジュールで使用されていることがわかりました。

## fix
`ws@0.8.0`が`Node.js@10.15.3`では使用することができないということがわかったので、
`sc5-styleguide`をアップデートして、エラーの起きないバージョンにするか、不要であれば削除することで**gyp ERR**は起きなくなります（はず）。

今回は`sc5-styleguide@1.0.0`を`sc5-styleguide@2.2.0`にアップデートすることでエラーは解消されました。

## さいごに
あまり再現しにくいエラーかとは思いますが、どなたかの参考になれば幸いです。

ライブラリのアップデートは骨の折れる作業が多いとは思いますが、
あとに残しておくと自分の首を締めることになりかねないのでこまめにアップデートしていくといいかと思います。
（Angularのアップデートもやらなきゃ...！）

今後も開発環境改善をしていく中で、面白い内容などがあれば記事にしていきたいと思っていますのでよろしくおねがいします！