npm install のエラー(zlib: incorrect data check)をRosettaで解決する（M1 Mac）

最近M1チップ搭載のMacBook Airを買い、環境構築を進めていたところで、このエラーにぶつかりました。
前々からM1チップはバグが多いみたいなことを聞いていましたが、これまでのIntel製チップと何が違うのかあまり理解していませんでした。
今回のエラーを通じて、M1チップというものがなんとなくわかったので、エラーの対処法と共に書いてみたいと思います。
このエラーに該当していない人でも、Rosettaの設定をしておくとM1チップの意味のわからないエラーも解決できるようになるかもしれないのでみてみるといいと思います。

# ぶつかったエラー
```
npm install -g typescript
```
nvmを用いてインストールをしたNode.js v14でtypescriptをグローバルにインストールすると下のようなエラーが出てしまいました。

```
zlib: incorrect data check
```
パッケージの中には普通にインストールできるものもあれば、同じようにzlibのエラーが出てしまうものもありました。

# 環境
MacBook Air (M1, 2020)
macOS Monterey v12.0.1

# 試したこと
同じようなエラーが出ていた[記事](https://stackoverflow.com/questions/69452504/zlib-error-when-attempting-to-run-npm-install-or-yarn)によると、v14.18.xのバグであると書いてあったので、v14.17に切り替えたり、また、npmのキャッシュを消したりと色々試してみたのですが、まったく解決には至らず途方に暮れていました。

# 解決方法
結論を先に書くと、Rosetta2を用いてx86アーキテクチャのhomebrewでnvmをインストールすることで解決しました。
ここからRosettaについて長々と書くので、Rosettaは知ってるよって人は[ここから](https://qiita.com/harusaku/items/ee3ceba2c56f45cf2e40#rosetta%E3%82%92%E9%80%9A%E3%81%97%E3%81%A6nvm%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B)お読みください。

## そもそもRosettaとは
Intel製チップとM1チップの違いの一つとして、CPUのアーキテクチャが違います。詳しく理解しているわけではないですが、 Intel製のチップ（x86）は命令セットがCISC（1命令が複雑なやつ）なのに対して、M1チップ（arm）はRISC（1命令が単純なやつ）らしいです。
しかし、世の中のソフトウェアはこれまでのIntel製のアーキテクチャ用に書かれたバイナリも多く、命令が違うということはそれらのソフトウェアをM1チップでは動かすことができないのかということになってしまいます。
そこで活躍するのがRosettaです。元々[Rosetta](https://ja.wikipedia.org/wiki/Rosetta)は昔MacのCPUのアーキテクチャがIntel製に変わる時に前のアーキテクチャのバイナリをx86アーキテクチャに変換してくれるものとして生まれたらしいです。そして今回新たにM1チップでarmアーキテクチャに変わるということで、Rosetta2としてｘ86用のバイナリをarm用に変換してくれるものが生まれました。
こいつを使うことで、これまでx86にしか対応していないソフトウェアもM1チップで動かすことができます。（これ以降Rosettaとは正確にはRosetta2のことです。）

Rosetta2は最初から装備されているわけではないですが、アプリケーションを入れるときに必要があればmacが自動的にインストールしてくれます。（[公式の解説](https://support.apple.com/ja-jp/HT211861)）

## ターミナルをRosettaを通して動かす
コマンドをRosettaで動かす際は二つ方法があります。個人的にはM1チップをせっかく買ったのなら基本的にはarmで動かしたいと思うので、2番目のやり方おすすめです。

1. GUIによる設定
Finderでターミナルアプリのアイコンを右クリックして、情報を見るを選択します。すると、下のようなウィンドウが出てくるので「Rosettaを使用して開く」にチェックを入れます。この状態でこのウィンドウを閉じ、ターミナルアプリを開くとx86アーキテクチャで動くようになります。armに戻したい際は同じ手順でチェックを外せばOKです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675277/acc65c83-2d11-34fe-f394-8d99d2e16395.png" width="40%">

1. コマンドライン上での切り替え
コマンドを実行する際に頭に```arch -x86_64```をつけるだけです。
例えば、

```Bash
$ arch -x86_64 ls
```
とすればｘ86で実行されることになります。（lsコマンドはあくまで例です）
また、多くのコマンドをx86で実行したければ、

```Bash
$ arch -x86_64 zsh
```
とすることで、Rosetta環境のzshが起動し、普通にコマンドを打てばRosettaを通して処理をしてくれます。
また、反対に```arch -arm64```を頭につければもとのarmアーキテクチャに戻すことができます。
これらをいちいち打つのはめんどくさいと思うので、下のようにエイリアスを設定するのがおすすめです。

```bash:.zshrc
alias x86='arch -x86_64 zsh'
alias arm='arch -arm64 zsh'
```
これで```x86```または```arm```と打つだけで切り替えが可能です。

また、今どちらの状態が使われているかは下のコマンドで確認できます。

```bash
# arm64 または　ｘ86のどちらかが出力される
$ uname -m
```

## Rosettaを通してnvmをインストールする
長くなりましたが、エラーの具体的な解決方法を説明していきます。
エラーの原因かどうかはわかりませんが、自分はhomebrewを普通にRosettaを通さずにダウンロードし、それを用いてnvmをインストールしていました。しかし、調べたところによるとnodeはv15以降しかarmに対応していないようでした。実際nvmを用いてv14.16.1をダウンロードし、以下のコマンドを実行すると、プロセスがx86であることが確認できます。

```bash
# v14以下だとx64と出力される
$ node -p process.arch
```

これは別にarmのhomebrewでインストールしたものでこうだったので、brewがarmであることがエラーの原因ではない気がするのですが、何をやっても解決しないので、Rosettaを通したbrewでインストールしてみることにしました。

インストール方法は[こちらの記事](https://zenn.dev/_lambda314/articles/63b851221a7016)を参考にしました。
簡単に説明すると、

1. x86環境でのhomebrewをインストールする。（ｘ86にzshを切り替えるまたは頭に```arch -x86_64```をつける）
1. ```.zshrc```に環境によって使うbrewを分けるように設定する。（これによって、二つのbrewの衝突を避けることができます）

これでRosetta環境にhomebrewがインストールできたら、あとは普通にnvmをインストール、nodeのバージョンを指定し、npmで必要なパッケージをインストールします。

```bash
#　nvmのインストール(このコマンドの出力に指示が書かれているのでそれに従う)
$ brew install nvm

# nodeのインストール(自分に必要なバージョンを指定)
$ nvm install v14.16.1

# パッケージをインストール
$ npm install -g typescript
```
この方法により、エラーが出ることなくインストールすることができました！

# まとめ
M1 Macを使っていて、「これはM1特有のバグっぽいな」と思ったらRosetta環境で試してみると解決することがありそうです。
（全部Rosettaでやってもいいんですが、せっかくのM1ならarmを主としたいよって感じです）

# 感想
このエラーに4日くらい費やしましたが、おかげでCPUのアーキテクチャの違いの他にも、あまり理解できていなかったzshの設定ファイルの書き方、Nodeのバージョンの切り替えなどいろんなことを知れました！
記事の書き方も知れてよかったです！！