Skip to content
コミットできない
Go back

Node.jsのバージョン管理

仕事でコードを書かなくなって久しいですが、仕事以外では色々書いています。

相変わらずNode.jsがメインで、最近はランタイムのバージョン管理ツールをいろいろ検討していました。

欲しいもの

自動的にバージョンを切り替えてくれるやつがほしい!

遍歴

  1. nvm
  2. nodebrew
  3. Volta

Voltaが一番好みに近かったですね。

インストールするとnodenpmコマンドのシンボリックリンク先がvoltaになり、nodeコマンドを実行した時に自動的にpackage.jsonを探してvoltaフィールドの値に切り替えてくれます。 devEnginesフィールドではないですが、それ以外はほぼ希望通りです。

Rust製でめちゃくちゃ快適だったのもプラスポイントです。

Voltaが開発停止

そんな感じで便利に使っていたんですが、数ヶ月前に “Volta is unmaintained.” というお知らせが…

https://github.com/volta-cli/volta

移行先としてmiseが推奨されています。 Voltaと同じように便利に使えるんだろうか…

miseを使ってみる

「まいす」「まいず」ではなく「みーず」と読むそうです。 正式名称は “mise-en-place” 、フランス語で「設定(setup)」だそうな。

Node.jsだけじゃなくてPythonやRubyにも対応しているらしい、というわけでとりあえずNode.jsで使ってみます。

まずはそれまで使っていたバージョン管理ツールやNode.jsなどをアンインストールして、node, npm, yarnなどのコマンドが使えない状態にしてください。

インストール

miseのインストールは、公式サイトにあるコマンド一発でできました。

curl https://mise.run | sh

インストール後にmiseアクティベーション用コマンドが表示されるので、忘れずに実行しておいてください。

別ターミナルを開いて、miseがインストールされたことを確認

$ mise -v
              _                                        __
   ____ ___  (_)_______        ___  ____        ____  / /___ _________
  / __ `__ \/ / ___/ _ \______/ _ \/ __ \______/ __ \/ / __ `/ ___/ _ \
 / / / / / / (__  )  __/_____/  __/ / / /_____/ /_/ / / /_/ / /__/  __/
/_/ /_/ /_/_/____/\___/      \___/_/ /_/     / .___/_/\__,_/\___/\___/
                                            /_/                 by @jdx
2026.3.9 macos-arm64 (2026-03-13)

設定

最低限LTSが動くようにグローバルにNode.jsをインストール。 ついでにNPMとYarnも。 お好みでbunpnpmなどもどうぞ。

mise use --global node@lts
mise use --global npm@latest
mise use --global yarn@1

多分必要な設定はこれだけ。

いよいよ動作テスト

適当なディレクトリーに.tool-versionsを作成して動作テスト。 書き方は、asdf.tool-versionsと同じ形式です。 今回は、このディレクトリーでNode.js v22を使うように設定してみます。

node 22

ファイルを作成した後でこのディレクトリーに移動すると、こんな警告が表示されます。 「Node.js 22が指定されているけどインストールされていないよ」と言われています。

mise WARN  missing: node@22.22.1

気にせずにnodeコマンドを使ってみます。

$ node -v
node@22.22.1    10.9.4
v22.22.1

自動的にインストールが始まり、v22が表示されました!

サブディレクトリーでも使える?

.tool-versionsがあるディレクトリーだけでなく、そのサブディレクトリー内でも自動的にダウンロードや切り替えができるかチェックしてみます。

今度は.tool-versionsに別のバージョンを指定してみます。

node 20

その後で、サブディレクトリーを作成してnodeコマンドを実行。

$ mkdir test

$ cd test
mise WARN  missing: node@20.20.1

$ node -v
node@20.20.1    10.8.2
v20.20.1

サブディレクトリーでもOK!

パッケージマネージャーも管理したい

Node.js本体だけじゃなくて、NPMとかYarnとかのパッケージマネージャーも同じように自動的に切り替えたいので、.tool-versionsを変えてみました。

node 22
npm 10
yarn 1.20

同じようにバージョンを確認

$ npm -v
10.9.4

$ yarn -v
1.20.0

無事切り替わりました。

ところで、以下のようにNode.jsのバージョンを24にすると、NPMのバージョンは10ではなく11になりました。

node 24
npm 10
$ node -v
v24.14.0

$ npm -v
11.9.0

NPMはピンポイントで自由にバージョンを指定できるわけではなく、対応するNode.jsがサポートしている最低バージョン以降を使えるのでしょうか。

package.jsonから自動判別したい

こちらによると、Node.js関連のツールはpackage.jsonを参照して切り替える機能があるようです! 素敵やん。

Pull Request(と元になったディスカッション)を見る限り、packageManagerdevEnginesフィールドを参照するようです。 Voltaは専用のvoltaフィールドを参照していたので、これよりも汎用性が高いですね。 素敵やん。

早速これも試してみましょう。

まず、以下のコマンドを実行してください。 node, npm, yarnのバージョン参照にpackage.jsonを使えるようになります。 お好みでbunpnpmなどもどうぞ。

mise settings add idiomatic_version_file_enable_tools node
mise settings add idiomatic_version_file_enable_tools npm
mise settings add idiomatic_version_file_enable_tools yarn

次に.tool-versionsを削除して、package.jsonを作成。

{
  "devEngines": {
    "runtime": {
      "name": "node",
      "version": "18"
    },
    "packageManager": {
      "name": "yarn",
      "version": "1.19"
    }
  }
}

そして実験。

$ node -v
v18.20.8

$ yarn -v
1.19.2

ちゃんと切り替わりました!

ただし、こちらもnpmは対応するNode.jsの最低バージョン以降に限定されるようです。

{
  "devEngines": {
    "runtime": {
      "name": "node",
      "version": "24"
    },
    "packageManager": {
      "name": "npm",
      "version": "10"
    }
  }
}
$ node -v
v24.14.0

$ npm -v
11.9.0

また、packageManagerの各プロパティーが配列の場合は最初の1つしか認識しないようで、たとえば以下のようにするとnodeyarnのバージョンを切り替えてくれません。 コメントで明記されているので、おそらくこれは仕様でしょう。

{
  "devEngines": {
    "runtime": [
      {
        "name": "bun",
        "version": "1.1"
      },
      {
        "name": "node",
        "version": "20"
      }
    ],
    "packageManager": [
      {
        "name": "npm",
        "version": "10"
      },
      {
        "name": "yarn",
        "version": "1.19"
      }
    ]
  }
}
$ node -v
v24.14.0

$ yarn -v
1.22.22

複数のランタイムやパッケージマネージャーを使いたい場合は.tool-versionsを使うのがよさそうです。

補完

シェルのタブ補完も対応しているようなのでやってみます。

まず補完スクリプトを生成&保存。 たとえばZ Shellならこんな感じ。 他のシェル用のコマンドは上記のリンク先を参照してください。

mise completion zsh  > /usr/local/share/zsh/site-functions/_mise

“permission denied” された場合は、以下のいずれかで。

そのあとで別ターミナルを開いて補完の確認ですが、こんなエラーが出て補完できない時があります。

Error: usage CLI not found. This is required for completions to work in mise.
See https://usage.jdx.dev for more information.

その場合は、以下のコマンドでusageコマンドを使えるようにしてください。

mise use --global usage

これでタブ補完が効くようになると思います。

まとめ

NPMだけ特別にバージョンを下げたいということも、runtimepackageManagerも複数指定することも個人的にはあまりないので、今のところ実用上の問題はなさそうです。

おかげでVoltaと決別する決心がつきました。 今までありがとう。 君のことは忘れないよ。


Share this post on:

Previous Post
昔見つけた円周率の公式
Next Post
Astro + GitHub Actions + Cloudflare Pagesで予約投稿