kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

〜スマートスピーカーやVoiceflowの記事は右メニューのカテゴリからどうぞ。〜

nvmからVoltaに変えてみたけど頓挫した・・・

f:id:kun432:20220319174947p:plain

Node.jsのバージョン管理に nodebrew、nvmと使ってきて、複数のバージョンを切り替えれるのはとても便利だけど、同じバージョンを複数の環境で分けたいというニッチな願望がちょっとだけあります。

  • 基本的にCLIのようなものでもグローバルにパッケージインストールしたくないので、プロジェクトのローカルにインストール、呼び出す場合はnpxを使う。
  • が、まれにnpxに対応していないものがある。package.jsonにscripts定義するのはちょっと面倒。グローバルにインストールせざるを得ない。

で、nodebrewやnvmでこういうことができるのか、というと、

  • nodebrewだとエイリアスを使えばできそうな気がしたけど、あくまでもバージョンの別名扱い
  • nvmも対応はしておらず、ここにあるようなワークアラウンド扱い

ということで、どちらもそうじゃない感がある。

いっそdockerでやってしまえなのかもと思いつつ、ちょっと別のバージョン管理ツールを試してみようということで、Voltaを試してみた。

目次

nvmのアンインストール

これだけで良いらしい。一応、.bashrcとか.bash_profileの記述も消した。

$ rm -rf ~/.nvm

Voltaのインストール

Homebrewでかんたん

$ brew install volta
$ volta --version
Updating your Volta directory. This may take a few moments...
1.0.5

ここちょっとハマったんだけど、Homebrewでインストールする場合はこれが必要みたい。

$ volta setup
Updating your Volta directory. This may take a few moments...
success: Setup complete. Open a new terminal to start using Volta!

.bashrcとかに以下のエントリが追加されてる。

export VOLTA_HOME="$HOME/.volta"
export PATH="$VOLTA_HOME/bin:$PATH"

これでOK。ターミナルを立ち上げ直しておく。

VoltaでNode.jsを管理してみる

volta install nodeで最新版のNode.jsを入れる。最新版のLTSが入るみたい。

$ volta install node
success: installed and set node@16.14.2 (with npm@8.5.0) as default

$ node -v
v16.14.2

node@〜でバージョン指定もできる。メジャーバージョンだけ指定するとその最新。細かく指定することも可能。下の方にある通り、volta installでは常にデフォルトが変更されるみたいで、これを変更するサブコマンドはちょっと見当たらない

$ volta install node@14
success: installed and set node@14.19.1 (with npm@6.14.16) as default

$ volta install node@14.19.0
success: installed and set node@14.19.0 (with npm@6.14.16) as default

$ node -v
v14.19.0

@latestだとLTSじゃない最新版になる。

$ volta install node@latest
success: installed and set node@17.7.2 (with npm@8.5.2) as default

volta listで現在使用しているバージョン、volta list allでインストールされているすべてのバージョンが表示される。

$ volta list
⚡️ Currently active tools:

    Node: v17.7.2 (default)
    Tool binaries available: NONE

See options for more detailed reports by running `volta list --help`.

$ volta list all
⚡️ User toolchain:

    Node runtimes:
        v14.19.0
        v14.19.1
        v16.14.2
        v17.7.2 (default)

    Package managers:


    Packages:

プロジェクト(ディレクトリ)ごとにバージョンを固定する場合はvolta pinを使う。

$ mkdir a && cd a
$ volta pin node@16
error: Not in a node package.

Use `volta install` to select a default version of a tool.

ん?と思ったけど、volta pinはpackage.jsonにバージョンを記載するので、そもそもnpm initしてないと使えない。

$ npm init -y
Wrote to /path-in-somewhere/a/package.json:

{
  "name": "a",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

$ volta pin node@16
success: pinned node@16.14.2 (with npm@8.5.0) in package.json

package.jsonを見てみる

$ cat package.json
{
  "name": "a",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "volta": {
    "node": "16.14.2"
  }
}

voltaの記述が増えている。プロジェクト内とプロジェクト外でのNode.jsのバージョンはどうなっているか?

$ pwd
/path-in-somewhere/a

$ node -v
v16.14.2

$ cd ..
$ pwd
/path-in-somewhere

$ node -v
v17.7.2

うん、ちゃんと分かれてる。では、別のプロジェクトを追加して、グローバルインストールしたパッケージがどうなるか見てみる。

$ mkdir b && cd b
$ npm init -y
$ volta pin node@16
$ npm install -g ask-cli
$ ask --version
2.26.0

$ cd ../a
$ pwd
/path-in-somewhere/a
$ ask --version
2.26.0

$ cd ..
$ ask --version
2.26.0

だめじゃん。かつ、プロジェクト外のデフォルトでも読み込めてる。

ドキュメントによると、

With Volta, installing a command-line tool globally with your package manager also adds it to your toolchain. For example, the vuepress package includes an executable of the same name:

yarn global add vuepress

When you install a package to your toolchain, Volta takes your current default Node version and pins the tool to that engine (see Package Binaries for more information). Volta won’t change the tool’s pinned engine unless you update the tool, no matter what. This way, you can be confident that your installed tools don’t change behind your back.

Understanding Volta | Volta

グローバルにインストールしたものはどうやらデフォルトのバージョンに紐づく様子。プロジェクト内・外で見比べてみると、

$ cd a
$ volta list
⚡️ Currently active tools:

    Node: v16.14.2 (current @ /path-in-somewhere/a/package.json)
    Tool binaries available:
        ask (default)
See options for more detailed reports by running `volta list --help`.

$  cd ..
$ volta list
⚡️ Currently active tools:

    Node: v17.7.2 (default)
    Tool binaries available:
        ask (default)

See options for more detailed reports by running `volta list --help`.

どうやらnpmパッケージもvoltaで管理がされる様子。なんだけど、両方ともdefaultになってるんだよな。ということであればpinすればいいのか?と思いきや、pinできるのはnodeとyarnだけらしい・・・

$ volta pin ask-cli@2.25.0
error: Only node and yarn can be pinned in a project

Use `npm install` or `yarn add` to select a version of ask-cli for this project.

ドキュメントにはこうもある。

The node and package manager executables aren’t the only smart tools in your toolchain: the package binaries in your toolchain are also aware of your current directory, and respect the configuration of the project you’re in.

For example, installing the Typescript package will add the compiler executable—tsc— to your toolchain:

npm install --global typescript

Depending on the project you’re in, this executable will switch to the project’s chosen version of TypeScript:

cd /path/to/project-using-typescript-3.9.4
tsc --version # 3.9.4

cd /path/to/project-using-typescript-4.1.5
tsc --version # 4.1.5

うーん、これを見る限りはできるはずなんだけど、どうすればこれが実現できるんだろう・・・

やっぱり、nodeenv使うべしなのかなー・・・

2022/3/21追記:

こちらでできました。

kun432.hatenablog.com