📝

nodeを16から18にアップデートした話

2022/11/21に公開

はじめに

node16系から18系にバージョンアップした手順を備忘録的に記事にまとめました。
nodeのバージョンアップによるパッケージの依存関係修復については触れません。
前提条件としてnodeのバージョン管理にvoltaを使用しています。

node 16.14.2 からnode 18.12.0へアップデートします。

手順

voltaのnodeのバージョンを上げる

node18の最新のLTSをインストール

$ volta install node@18

voltaにインストールされているバージョンを確認

$ volta list all
$ volta list all
⚡️ User toolchain:

    Node runtimes:
        v6.17.1
        v8.17.0
        v10.24.1
        v12.22.7
        v12.22.11
        v12.22.12
        v14.19.1
        v16.14.2
        v16.15.0
        v16.18.0
        v16.18.1
        v18.12.0 (current @ {プロジェクトのパス})
        v19.0.0

nodeのバージョン指定

$ volta pin node@v18.12.0

nodeのバージョン確認

$ node -v
v18.12.0

node_modulesを再インストール

node_modules削除

$ rm -i -rf node_modules    

yarn.lock削除

$ rm -f yarn.lock

cache削除

$ yarn cache clean  

node_modules再インストール

$ yarn install

これでnodeV18系のnode_modulesが再インストールされました。

動作確認

動作確認としてアプリを起動させると。。。

$ yarn dev

以下のエラーが発生しました。

 ERROR  Error: error:0308010C:digital envelope routines::unsupported 

OpenSSLの互換性エラー

Node16ではOpenSSL1.1を使用していましたが、Node17からはOpenSSL3.0に変更されたことで互換性が取れずにエラーになっているようです。

https://zenn.dev/yogarasu/articles/425732ff408d06

このエラーを回避するためにnodeのオプションでopenssl-legacy-providerを指定し、古いプロバイダーを使用することで回避できます。

export NODE_OPTIONS=--openssl-legacy-provider

ビルド時にオプションを指定するためにpackage.jsonのscriptsに追記しました。

  "scripts": {
    "dev": "node --openssl-legacy-provider node_modules/.bin/next dev",
  },

ECONNREFUSEDエラー

これでもう一度ビルドしてみるとビルド自体は成功しますが、サーバー側のAPIでECONNREFUSEDエラーが発生しています。クライアント側では叩けているのでサーバー側だけで発生していそうです。

get: http://{エンドポイント} - ECONNREFUSED

node16まではIpv4に接続することがデフォルトになっていたようですが、node18からはIpv6に優先して接続するようになったことが原因のようです。

https://www.reddit.com/r/ipv6/comments/qbr8jc/nodejs_finally_prefers_ipv6_addresses_over_ipv4/

その関係でIPv6のみ接続が拒否されているためサーバー側でホストが失敗してECONNREFUSEDエラーになっています。
クライアント側だけ成功した原因はわかっていないのですが、クライアント側でIPv6で繋がらない場合はIPv4で接続する設定が効いているのでしょうか?わかる人いれば教えて欲しいです。

こちらのエラーもnodeのオプションでdns-result-orderorderipv4firstに指定し、IPv4を優先させれば良いです。

本来であればIPv6で繋がらなければIPv4に接続する設定ができれば良いと思うのですが、ここでは暫定的にIPv4を優先する設定を行いました。

export NODE_OPTIONS=--dns-result-order=ipv4first

こちらもscriptに記載しました。

  "scripts": {
    "dev": "node --openssl-legacy-provider --dns-result-order=ipv4first node_modules/.bin/next dev",
  },

最終確認

最後にもう一度ビルドして動作確認をします。

$ yarn dev

パッケージの依存関係が出たら依存関係を調べて修復する必要がありますが、node自体のアップデートはできたので一旦完了です。

おわりに

nodeのアップデート自体はそこまで大きな問題なくできるんですが、問題はパッケージの依存関係ですね。
あとやっぱりvoltaでnodeのバージョン管理する運用がされてると便利ですね。

参考記事

https://zenn.dev/844/articles/0e1bdf3bb75ca3
https://nullnull.dev/blog/how-to-use-volta-in-mac/
https://zenn.dev/yogarasu/articles/425732ff408d06
https://qiita.com/raiga0310/items/ba198156cfb5a5f8462b
https://www.reddit.com/r/ipv6/comments/qbr8jc/nodejs_finally_prefers_ipv6_addresses_over_ipv4/

Discussion