Closed8

voltaの導入と感想

mars2nicomars2nico

やることが減って新しいことができるようになった。
できるようになったが選べるわけではない。
ずっと避けていたがNodejsをしっかり見て使わざるを得なくなった。

voltaを導入した。

> volta -v
2.0.2
> volta --help
The JavaScript Launcher ⚡

    To install a tool in your toolchain, use `volta install`.
    To pin your project's runtime or package manager, use `volta pin`.

Usage: volta.exe [OPTIONS] [COMMAND]

Commands:
  fetch        Fetches a tool to the local machine
  install      Installs a tool in your toolchain
  uninstall    Uninstalls a tool from your toolchain
  pin          Pins your project's runtime or package manager
  list         Displays the current toolchain
  completions  Generates Volta completions
  which        Locates the actual binary that will be called by Volta
  setup        Enables Volta for the current user / shell
  run          Run a command with custom Node, npm, pnpm, and/or Yarn versions
  help         Print this message or the help of the given subcommand(s)

Nodeはプロジェクトごとにスイッチして切り替えるものと覚えていたがスイッチらしいものが見当たらない。
「volta node 切り替え」――Webで検索。

どうもpackage.jsonvoltaの部分を参照して勝手に切り替えるらしい。

どういうびっくり技術なのか調べる。

mars2nicomars2nico

調査するポイント

  • voltaはランチャー
  • 起動する(管理する)配信元
    • node
    • yarn
    • パッケージ
  • voltaはランチャーなのか?yarnはパッケージマネージャーなのか?
  • そもそもvoltaやyarnが取得するパッケージは検証されているのか
mars2nicomars2nico

voltaはランチャー 1/?

実行ファイルの確認方法

> where.exe node
C:\Program Files\Volta\node.exe
> where.exe yarn
C:\Program Files\Volta\yarn.cmd
C:\Program Files\Volta\yarn.exe
> Get-Content 'C:\Program Files\Volta\yarn.cmd'
@echo off
"%~dpn0.exe" %*
> comp.exe 'C:\Program Files\Volta\node.exe' 'C:\Program Files\Volta\volta-shim.exe' /M
C:\Program Files\Volta\node.exe と C:\Program Files\Volta\volta-shim.exe を比較しています...
ファイルに違いはありません
> comp.exe 'C:\Program Files\Volta\node.exe' 'C:\Program Files\Volta\yarn.exe' /M
C:\Program Files\Volta\node.exe と C:\Program Files\Volta\yarn.exe を比較しています...
ファイルに違いはありません

volta-shimがどうも本体らしい

ソースコードからビルドして確認

> git checkout v2.0.2
> cargo b -r
> cd .\target\release\
> cp .\volta-shim.exe node.exe

ここでできあがったvolta-shimをnodeとして起動してあげるとインストールされたもの同じ動作をすると思ったがうまく動かない

mars2nicomars2nico

配置先だけの問題だったようだ。ビルドしてできたvolta-shimをすでに存在するC:\Program Files\Volta\node.exeと置き換えて使用するとうまく動いた。

mars2nicomars2nico

voltaはランチャー(2/?)

voltaのソースコードを読む (1/?)

要約

プロジェクトのフォルダ構造は「アプリ本体(exe)」と「同名のライブラリ」でソースコードが分離されていて、これはCLIやGUIを持つOSSのライブラリではffmpeg.exe/ffplay.exe対libffmpeg, obs.exe対libobsなどでもみられる形体である。
先に調べた通りvoltaインストール環境下ではnode.exeyarn.exevolta-shim.exeである。
ソースコードを読むとffmpegやobsの例にならって、volta.exe/volta-shim.exe対volta-coreといった風な構造が見えた。調べた結果、トップレベル(CLI)で見える機能とコア機能の対応関係は下表の通り。

トップレベル機能 コアロジック コメント ソースコードへのリンク
volta-shim get_executor ../run/mod.rs#L75
volta run get_executor 呼び出し方がshimと異なるので若干補助機能に差分がある ../run/mod.rs#L75
volta install ensure_fetch (ステータス:要確認)
volta pin ensure_fetch (ステータス:要確認)
mars2nicomars2nico

voltaはランチャー(3/3)

voltaのソースコードを読む (2/?)

volta run

ヘルプを確認するとこのような説明が出てくる。

> volta run --help
Run a command with custom Node, npm, pnpm, and/or Yarn versions

Usage: volta.exe run [OPTIONS] <COMMAND>...

Arguments:
  <COMMAND>...  The command to run, along with any arguments

Options:
      --node <version>    Set the custom Node version
      --npm <version>     Set the custom npm version

説明にはないがソースコード[1]を読むとRustの標準ライブラリを通じて環境変数を指定している。

executor.rs
use std::process::{Command, ExitStatus};
:
pub struct ToolCommand {
    command: Command,
    platform: Option<Platform>,
    kind: ToolKind,
}
:
impl ToolCommand {
:
    pub fn env<K, V>(&mut self, key: K, value: V)
    where
        K: AsRef<OsStr>,
        V: AsRef<OsStr>,
    {
        self.command.env(key, value);
    }
:
    pub fn execute(mut self, session: &mut Session) -> Fallible<ExitStatus> {
:
        self.command.env("PATH", path);
:

そのためコマンドvolta run --node v14.16.0 powershell -Command "node -v; pause"を試しに実行してみると

v14.16.0
続行するには、Enter キーを押してください...:

と返ってきた。うーん変態だ!(ほめてる。)

脚注
  1. volta/crates/volta-core/src/run/executor.rs at v2.0.2 · volta-cli/volta ↩︎

mars2nicomars2nico

起動する(管理する)配信元(1/?)

要約

nodeの場合、配信元 https://nodejs.org/dist から取得する。
yarnの場合、配信元 https://registry.npmjs.org/ から取得する。
パッケージの場合は子プロセスとしてyarnが間接的に起動する。このパッケージはVoltaの管理外になる。例外としてグローバルにパッケージをインストールする場合があって、その場合、パッケージはVoltaの管理下に入る。

グローバルにパッケージをインストールする際はVoltaによって環境変数npm_config_prefixが上書きされるためマシンの設定は無視される。これは環境変数PAHTいわゆる「コマンドサーチパス」という仕組みを利用するOSの都合、同じマシン内でVoltaが他のnodeバージョン管理ソフトと共存できない原因になりうる。

voltaの管理下にあるnodeの確認方法

nodeのプロジェクトフォルダ以外の場所でvolta listvolta whichを使う。

> volta list --help
Displays the current toolchain

Usage: volta.exe list [OPTIONS] [tool]
:
> volta which --help
Locates the actual binary that will be called by Volta

Usage: volta.exe which [OPTIONS] <BINARY>

Arguments:
  <BINARY>  The binary to find, e.g. `node` or `npm`
:
> Test-Path package.json
False
> volta list
⚡️ Currently active tools:

    Node: v20.3.0 (default)
    Yarn: v1.22.19 (default)
    Tool binaries available:
        vue (default)

See options for more detailed reports by running `volta list --help`.
> volta which node
C:\Users\:USERNAME\AppData\Local\Volta\tools\image\node\20.3.0\node.exe
> volta which yarn
C:\Users\:USERNAME\AppData\Local\Volta\tools\image\yarn\1.22.19\bin\yarn.cmd

volta pinされたnodeのプロジェクト配下ではwhichの結果が変わる(listの結果も変わるが省略)。

> Test-Path package.json
True
> volta which node
C:\Users\:USERNAME\AppData\Local\Volta\tools\image\node\14.16.0\node.exe

なお、volta listで有効になっていなくてもwhichで見つけることができる。

> volta which npm 
C:\Users\:USERNAME\AppData\Local\Volta\tools\image\node\20.3.0\npm.cmd
> volta which pnpm
C:\Program Files\Volta\pnpm.exe
mars2nicomars2nico

voltaはランチャーなのか?yarnはパッケージマネージャーなのか?(感想)

要旨

voltaはnodeバージョン管理ウェアであって、パッケージマネージャーマネージャーだ。ビルドツールのランチャーであって、ビルドした後のアーティファクトにvoltaが直接かかわることはない……と思う。voltaの全部のソースを読んだわけでない為。

スクラップの書き始めにはyarnとクロスする部分があるのではないかと疑っていたが、少なくとも私がvoltaを使う分にはクロスする部分は全くなさそう。

「そもそもvoltaやyarnが取得するパッケージは検証されているのか」についてはvoltaが仮に直接的にパッケージ管理をしているとしたらといったところがモチベーションだった。
それがなくなってしまったのでまた別のモチベーションがでてきたら調べるものとする。

このスクラップは5ヶ月前にクローズされました