node v8.1.4以下はnpmをアップデートしてから使いましょう



（追記）v8.2.0がリリースされて、npm 5.3.0がバンドルされるようになったので、最新版を使うなら問題なくなりました。

# とりあえず、結論

2017/07/18の時点で最新版のnode.js v8.1.4ではnpm v5.0.3がバンドルされているが、特定の状況でnpm installするとインストール済みの必要な依存ライブラリが削除されるので、npmをアップデートしてから使ったほうがよい。（npm v5.2.0では起こらないことを確認済み）

# どういう状況で起こるか

すでにライブラリがインストールされている状況で、ライブラリのバージョンを上げた `package.json` , `package-lock.json` を持ってきて `npm install` すると、バージョンが上がったライブラリの依存ライブラリが全て削除される。ということが起る。

今回は `express` を `v4.15.2` => `v4.15.3` にアップデートする想定で試してみます。

## 確認環境

- node v8.1.4
- npm v5.0.3

## 再現

### アップデート後のファイル用意

まず事前準備として、アップデート後のファイルを用意します。一応、他のチームメンバーがアップデートしたとか、本番反映するときとかを想定していますが、今回はテストなので適当に別のディレクトリなどで、用意しました。

```package.json
{
  "name": "sample",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "license": "ISC",
  "dependencies": {
    "express": "^4.15.3"
  }
}
```

これと、これでインストールした生成された `package-lock.json` を用意しておきます。

### アップデート前

アップデート前の `package.json` はこちらです。

```package.json
{
  "name": "sample",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "license": "ISC",
  "dependencies": {
    "express": "4.15.2"
  }
}
```

これを `npm install` すると、 `package-lock.json` が生成されます。これで依存ライブラリを含む express v4.15.2 がインストールされた状態になりました。

```
$ npm ls | grep express
└─┬ express@4.15.2
```

### 実行

ここに先程用意したアップデート後の `package.json` と `package-lock.json` をチェックアウトするなり、置き換えるなりして持ってきます。diffはこんな感じです。

```
diff --git a/package-lock.json b/package-lock.json
index b68f31c..9882258 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -34,9 +34,9 @@
       "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
     },
     "debug": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.1.tgz",
-      "integrity": "sha1-eYVQkLosTjEVzH2HaUkdWPBJE1E="
+      "version": "2.6.7",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz",
+      "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4="
     },
     "depd": {
       "version": "1.1.0",
@@ -69,26 +69,14 @@
       "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE="
     },
     "express": {
-      "version": "4.15.2",
-      "resolved": "https://registry.npmjs.org/express/-/express-4.15.2.tgz",
-      "integrity": "sha1-rxB/wUhQRFfy3Kmm8lcdcSm5ezU="
+      "version": "4.15.3",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz",
+      "integrity": "sha1-urZdDwOqgMNYQIly/HAPkWlEtmI="
     },
     "finalhandler": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz",
-      "integrity": "sha1-70fneVDpmXgOhgIqVg4yF+DQzIk=",
-      "dependencies": {
-        "debug": {
-          "version": "2.6.7",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz",
-          "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4="
-        },
-        "ms": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-        }
-      }
+      "integrity": "sha1-70fneVDpmXgOhgIqVg4yF+DQzIk="
     },
     "forwarded": {
       "version": "0.1.0",
@@ -146,9 +134,9 @@
       "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0="
     },
     "ms": {
-      "version": "0.7.2",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
-      "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U="
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
     },
     "negotiator": {
       "version": "0.6.1",
@@ -186,14 +174,14 @@
       "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
     },
     "send": {
-      "version": "0.15.1",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.15.1.tgz",
-      "integrity": "sha1-igI1TCbm9cynAAZfXwzeupDse18="
+      "version": "0.15.3",
+      "resolved": "https://registry.npmjs.org/send/-/send-0.15.3.tgz",
+      "integrity": "sha1-UBP5+ZAj31DRvZiSwZ4979HVMwk="
     },
     "serve-static": {
-      "version": "1.12.1",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.1.tgz",
-      "integrity": "sha1-dEOpZePO1kes61Y5+ga/TRu+ADk="
+      "version": "1.12.3",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.3.tgz",
+      "integrity": "sha1-n0uhni8wMMVH+K+ZEHg47DjVseI="
     },
     "setprototypeof": {
       "version": "1.0.3",
diff --git a/package.json b/package.json
index 9e0ff27..dae240e 100644
--- a/package.json
+++ b/package.json
@@ -5,6 +5,6 @@
   "private": true,
   "license": "ISC",
   "dependencies": {
-    "express": "4.15.2"
+    "express": "^4.15.3"
   }
 }
```


この状態でnpm installすると、

```
$ npm install
removed 40 packages and updated 4 packages in 1.076s
```



＿人人人人人人人人人人人＿
＞　removed 40 packages　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y￣


```
$ npm ls
sample@1.0.0
└─┬ express@4.15.3
  ├── UNMET DEPENDENCY accepts@~1.3.3
  ├── UNMET DEPENDENCY array-flatten@1.1.1
  ├── UNMET DEPENDENCY content-disposition@0.5.2
  ├── UNMET DEPENDENCY content-type@~1.0.2
  ├── UNMET DEPENDENCY cookie@0.3.1
  ├── UNMET DEPENDENCY cookie-signature@1.0.6
  ├── UNMET DEPENDENCY debug@2.6.7
  ├── UNMET DEPENDENCY depd@~1.1.0
  ├── UNMET DEPENDENCY encodeurl@~1.0.1
  ├── UNMET DEPENDENCY escape-html@~1.0.3
  ├── UNMET DEPENDENCY etag@~1.8.0
  ....
```

ということで、依存ライブラリを全部削除してくれます。

あまり詳しく調べてはいないのですが、挙動的にはinstallの際に `package-lock.json` を見てインストールする、ライブラリに更新があった場合には依存がなくなっている可能性があるので、不要になったライブラリを探してremoveする。みたいな処理がバグってて、依存関係もろとも全部削除してる。んですかね？

# 対策

冒頭にも述べましたが、npm v5.2.0ではこの現象が起こらないことを確認しました。v5.1.0からrequireという依存関係の記述が `package-lock.json` に追加されたことで修正されたっぽい？

まぁとりあえず、アップデートしましょう。ということで。


# 終わりに

npm v5.2.0で新しくバンドルされた `npx` に気を取られていました。が、気にしないといけないのは目玉機能だけじゃないよ！ということで。

（詳しく調べたら追記するかも？）