npm 7（8） でフロントエンド開発に関わる変更まとめ

npm 7 が 6 から結構変わっていたのでそのまとめです。
普段、yarn はあまり使わず、pnpm も使ったことないユーザなので
情報の片手落ちなどがありましたらご指摘いただけると助かります:bow:

## npm 7 について
Node.js v15 から npm 7 がインストールされるようになりました。
2021/10/26 から Node.js v16 が LTS になったので、
npm 7 以上を利用する機会が今後増えると思います。

npm 6 から 7 での**フロントエンドに関する**大きな変更点と思われる箇所は下記。

- peerDependency の挙動変更
- packege-lock.json のフォーマット変更
- yarn.lock のファイルサポート
- npm audit の出力変更
- workspace のサポート

バックエンド含め、そのほかの変更箇所は下記の記事が詳しいです。
[npm v7の主な変更点まとめ](https://blog.watilde.com/2020/10/14/npm-v7%E3%81%AE%E4%B8%BB%E3%81%AA%E5%A4%89%E6%9B%B4%E7%82%B9%E3%81%BE%E3%81%A8%E3%82%81/)

### peerDependency の挙動変更

パッケージの依存関係を記載していた peerDependency の機能が強化され、
dependenciesやdevDependenciesに、peerDependenciesと矛盾するバージョンをインストールすると下記のようなエラーができるようになりました。

```
ERESOLVE unable to resolve dependency tree
```

Next.js などを使ってこの問題が起きたときは、
npm install コマンドに `--legacy-peer-deps` オプションをつけることで
一時的に npm 6以前の挙動でパッケージをインストールすることが可能です。

### packege-lock.json のフォーマット変更
npm 7 から、packege-lock.json のフォーマットが変わり、
**lockfileVersion** バージョンが 1 から <font color="red">2</font> になりました。

パッケージツリーを完全に構築するために必要なすべての情報が含まれるようになり、
これによって yarn.lock のファイルサポート、workspace のサポートが
可能になりました。

実際に npm を使う人にとって一番の関心ごとは
「バージョンが異なっても今まで通り使えるのか？」だと思います。
npm  7 と 6 それぞれでパッケージのインストールがどう変わるか下記にまとめました。


| |  lockfileVersion が 1 | lockfileVersion が 2 |
|:-----------|:-----------|:-----------|
| npm6 で<br>$ npm ci | 問題なし | npm の update を促されるが問題なし。lockfileVersion は2のまま |
| npm6 で<br>$ npm install | 問題なし | npm の update を促されるが問題なし。lockfileVersion は1になる |
| npm7 で $ npm ci | 警告が出るが問題なし。lockfileVersion も1のまま | 問題なし |
| npm7 で $ npm install | 警告が出るが問題なし。lockfileVersion は2になる |  問題なし |

lockfileVersion と npm 対応バージョンが違っても、
パッケージのインストールは問題なくできるようです。

しかし、lockfileVersion が 2 の packege-lock.json を使っているときに
npm 6 の `$ npm audit` を実行すると

```
npm ERR! Cannot read property ‘fetchSpec’ of undefined
```

のエラーが出ることがありました。
（モジュール再インストールで解消しましたが、なぜエラーが発生するのか謎。。）

仕事では、チームで npm のバージョンを統一しておいた方が良いと思っています。

### yarn.lock のファイルサポート
yarn で パッケージを管理すると yarn.lock が生成され package-json.lock は発生しません。
しかし、yarn.lock は yarn のバージョンでフォーマットが異なり、
同じプロジェクト内でも yarn のバージョンが統一されていなかったら
パッケージのバージョン固定が担保されない場合がありました。
参考：[npm v7 Series - Why Keep package-lock.json?](https://blog.npmjs.org/post/621733939456933888/npm-v7-series-why-keep-package-lockjson)
（yarn のバージョン差異による yarn.lock の差分は [yarn policies](https://classic.yarnpkg.com/en/docs/cli/policies/#toc-policies-set-version) で解消できる）

lockfileVersion 2 の package-json.lock では、
パッケージツリーを構築するための全ての情報が揃っているので、
この問題を解消することができます。

package-json.lock と yarn.lock が共存するプロジェクトの場合、
`$ npm install` や `$ yarn add` などで追加・更新・削除されたパッケージの情報はどちらのファイルにも自動で共有されます。

yarn をメインに使っているプロジェクトで、package-json.lock を作るのは
保険的に良いのでは…… 程度しかメリットを理解していないのですが、
npm と yarn の互換性が上がったことで CI など環境統一の負荷が減るのは
有り難いことじゃなかろうかと想像しています。

### npm audit の出力変更

npm 7 以降で `$ npm audit` の出力方法だけでなく、
脆弱性レベルの判定も変わったみたいです。

下記はあるプロジェクトの audit の結果です。

| npm<br> バージョン | audit 結果 |
|:-----------|:-----------|:-----------|
| 6 | found <font color="red">53 vulnerabilities</font> (1 **low**, 37 **moderate**, 15 **high**) in 1969 scanned packages<br>run `npm audit fix` to fix 35 of them.<br>18 vulnerabilities require manual review. See the full report for details.|
| 7 | <font color="red">52 vulnerabilities</font> (1 **low**, 22 **moderate**, 29 **high**) |

7系だと脆弱性の数も変わり、high が増えましたね。。
どうやら脆弱性のあるパッケージの依存ルートの考え方が変わったためらしいのですが、
わかりにくく「改悪」としている人がいました。

 参考：[Dealing with NPM v7 Audit Changes](https://uko.codes/dealing-with-npm-v7-audit-changes)

表示も、6系と 7系で大きく異なります。

6系の出力サンプル
![スクリーンショット 2021-10-26 17.39.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131281/9e328aa5-e64a-16bd-eb37-3342c0d8fdfc.png)

7系の出力サンプル
![スクリーンショット 2021-10-26 17.41.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131281/b5bc619f-ea92-7bdf-79f9-36697b4a116e.png)


7系ではレポートを見易く出力するために `$ npm audit —-json` というオプションが追加されました。7系で人がレポートを確認する際は、こちらを参照してください。
下記は出力される json の例です。

```.json
{
  "auditReportVersion": 2,
  "vulnerabilities": {
    "axios": {
      "name": "axios",
      "severity": "high",
      "isDirect": true,
      "via": [
        {
          "source": 1002477,
          "name": "axios",
          "dependency": "axios",
          "title": "Incorrect Comparison in axios",
          "url": "https://github.com/advisories/GHSA-cph5-m8f7-6c5x",
          "severity": "high",
          "range": "<=0.21.1"
        }
      ],
      "effects": [
        "localtunnel"
      ],
      "range": "<=0.21.1",
      "nodes": [
        "node_modules/axios"
      ],
      "fixAvailable": true
    },
  〜 省略 〜
  },
  "metadata": {
    "vulnerabilities": {
      "info": 0,
      "low": 1,
      "moderate": 22,
      "high": 29,
      "critical": 0,
      "total": 52
    },
    "dependencies": {
      "prod": 7,
      "dev": 1959,
      "optional": 6,
      "peer": 0,
      "peerOptional": 0,
      "total": 1965
    }
  }
}
```

fixAvailable で一発解消できるか示してくれたところは親切かな……？
機械的に処理しやすくなったけど、エンジニアが手動でアップデートする場合は
前の方がやり易かった気がします。


### workspace のサポート

今まで Monorepo で開発してきた人は、Lerna と yarn などを組み合わせて使っていたと
思いますが、npm 7 からも workspace のサポートが開始されました。
多分 npm 的にはこの追加が一番革新的な変更だったと思います。

[Getting Started with npm Workspaces](https://ruanmartinelli.com/posts/npm-7-workspaces-1) を参考に
npm workspace を試してみたのですが、簡単に Monorepo を試すことができました。
yarn, pnpm と類似性も多く、これらのツールと置き換えもできそうです。

しかし、実際 twitter では yarn の workspace から npm に切り替えて不具合があった、
という声をちらほら見かけました。

まだ情報が少ないので、使い勝手は劣るのかもしれないのですが、
これから導入事例が増えることで他のツールと遜色ないものになるのではないか…と考えています。



### おまけ：npm 8 について
Node.js 16.11.0 以降から npm 8 が同梱されるようになりました。

npm 8 は npm 7 に比べると、フロントエンドまわりに大きな変更はありませんでした。
（今のところ）
参考：[npm 8.0 リリースノート](https://github.com/npm/cli/releases/tag/v8.0.0)

npm 6 から npm 8 に一気に上げて、使い勝手が変わった？という人は
npm 7 の変更内容などを確認すると参考になるかもしれないです。