⚙️

言語環境の管理は *env や *vm を超えて、 mise へ

2024/09/11に公開

mise はミーズと読みます。

mise とは

*env や *vm が担っていた言語環境(コンパイラ・インタプリタ)のバージョンを管理するツールです。
rbenv や nvm のように単一言語に対するサポートではなく、標準で Go、 Node.js、 Python などの複数の言語に対応しています。
類似のソフトウェアに asdf が存在しますが、 mise はその精神的後継となっています。asdf が shell で書かれていたのに対し、 mise は rust で実装されており、起動速度も asdf と比べて格段に早くなっています。

mise は The front-end to your dev env. と自称しており、上記の言語環境のみならず、アウトオブボックスで使用できる複数の開発向けの機能を提供しているので、本稿で紹介します。

言語環境の用意

mise が提供する言語環境はまず大きく 2 つに分類されます。標準でサポートしている言語と、 asdf plugin によるものです。

執筆時点 (2024/09/11) で標準でサポートされている言語は以下になります。

  • Bun
  • Deno
  • Erlang (Experimental)
  • Go
  • Java
  • Node.js
  • Python
  • Ruby

Rust については、 mise 公式から「rustup があるのだから mise は必要ない」と言及されています。しかしインストールについて関与しないのみで、フロントエンドとして rust のバージョンを config で管理することは可能となっています。

mise install node@20.8.0
mise use -g node@20.8.0

上記の設定をすると、 config ファイルは以下のようになります。

[tools]
node = "20.8.0"

なおこのバージョンには latest を指定することもできます。mise が outdated を教えてくれるため、そのタイミングでアップデートすることができます。

また、plugin でサポートされている言語については、代表的なものは以下になります。plugin を含めると、言語問わず著名な cli ソフトウェアは対応されています。

  • Elixir
  • Zig (Zigmod)
  • jq
  • awscli
  • terraform
    ...

mise では asdf の Plugin と互換性があり、公式で使用可能です。Plugin の一覧として、 asdf 公式にまとまっているものが参考になります。
https://github.com/asdf-vm/asdf-plugins

plugin のインストール処理を自分で実行しなくとも、 mise install awscli@latest などとすると自動でインストールされます。

これらの言語は、 .mise.toml ファイルに設定することによって管理されます。
詳しくはドキュメントに記載がありますが、カレントディレクトリからユーザ、システムと遡って設定ファイルを確認し、マージする挙動をします。そのため、プロジェクトごとの設定とグローバルの設定はうまくマージされて共存します。

言語環境以外の機能

mise が The front-end to your dev env. と自称する通り、このソフトウェアは言語環境を管理するためだけのものではありません。
mise は 3 大機能として、以下の通り提唱しています。

  • Like asdf (or nvm or pyenv but for any language) it manages dev tools like node, python, cmake, terraform, and hundreds more.
  • Like direnv it manages environment variables for different project directories.
  • Like make it manages tasks used to build and test projects.

1 つ目は前述の通り言語環境の管理です。
2 つ目として、 direnv のような、ディレクトリと対応して環境変数を自動的に読み込む機能が提供されています。
3 つ目として、 make に変わるタスクランナー、ビルドツールとしての機能が提供されています。

環境変数管理機能

前述の通り、 .mise.toml は個別のディレクトリ配下にも配置することを想定されています。
例えばそのディレクトリで特定の環境変数を使用したい場合は、以下の通り設定に記載します。

[env]
PORT=3001

これを設定すると mise trust をしろと言われるかもしれません。trust したことがないディレクトリに対しては毎回求められます。無効化する方法もありますが、安全のため推奨しません。
trust した状態でこの作業ディレクトリに入り、以下のようにして環境変数を確認します。

echo $PORT

そうすると、 3001 が設定されていることがわかります。
この設定ファイルの置いてあるディレクトリから親に移動して再度上記を実行すると、設定が消えていることがわかります。このように影響をディレクトリに閉じて環境変数を設定することができます。
上記のような toml での定義だけでなく、 .env ファイルを参照することもできます。

[env]
_.file = ".env"

その他の詳細な挙動はドキュメントに完結にまとまっています。
https://mise.jdx.dev/environments.html
_.file の他にも PATH を拡張する _.path や特定の shell ファイルを source する _.source なども存在します。

タスクランナー機能

mise のタスクランナー機能は experimental ですが、現状問題なく使用することができます。
このタスクランナーはビルダーとして多機能であり、ビルド依存や最終変更などを監視したり、 watch することで自動的に再ビルドを実行することもできます。
こちらもまた公式のドキュメントが完結かつ充足しているのですが、簡単に説明すると、以下のように書くとコマンドラインで実行できます。

[tasks.build]
run = go build main.go
mise run build

最近の言語だとタスクランナーが標準でついていることも多いですが、 Go などでは便利かと思います。

他にも、npm backend なライブラリを管理したり

現状 Experimental ですが、 mise は各言語のパッケージマネージャをバックエンドにしたライブラリの管理もできます。
https://mise.jdx.dev/dev-tools/backends/

たとえば、 npm をバックエンドにして prettier を Node.js のバージョン問わず グローバルにインストールする、などもできます。

[tools]
"npm:prettier" = "latest"

こうしておくと、 Node のバージョンを変えても prettier には常にアクセスできます。複数の Node バージョンがプロジェクト別に存在するが global では常に最新の prettier を使用したい、などの場合に有効です。

mise をプロジェクト共通とするべきか

筆者は mise をプロジェクト標準とすべきかはケースバイケースであると考えます。
まず開発環境が個々人でどれだけ異なるか、どれだけ自由が求められる風土かによっても異なります。
たとえば同一バージョンのインタプリタが入っていれば言語管理は何でも良いというチームもあれば、バージョン管理ツールまで指定されるチームもあります。Windows と Linux で共同開発するチームもあるかもしれません。
ですので、チームに無理のない範囲で導入できるのが良いと思います。
そしてチーム標準とならずとも、自分だけ mise を活用すればよいのです。
例えば direnv のようなツールはグローバルの shell に設定が必要となるため強制したくなく、プロジェクトでは「このようなツールを使うのが便利です」という紹介に留め、例として direnv や mise を挙げ、自分は mise を使う、という方法を取るなどです。
タスクランナー機能についても、自分だけが触る範囲であれば自分だけの .mise.toml を作るのもよいでしょう。ただし複数人で管理する場合に make に限界がきているのであれば、プロジェクトとしての mise の導入を提案してもよいかもしれません。

Discussion