はじめに
以前は nodenv、pyenv、direnv などのツールをそれぞれ使っていましたが、プロジェクトごとに設定ファイルやコマンドが散らばるのが気になっていました。
そこで、Rust 製のツールマネージャー mise1 に乗り換えてみたところ、管理が非常にスッキリしました!
動作が非常に高速というメリットもあるようです🙌
mise とは
mise は言語バージョン・環境変数・タスク定義を1つのファイル(mise.toml)で一元管理できる Rust 製のツールマネージャーです。
主に以下のメリットがあります。
- 言語バージョン、環境変数、タスク定義を
mise.tomlにまとめて管理できる - Node.js, Python, Go などの主要なツールに対応しており、asdf プラグインや既存の
.tool-versionsも活用できる -
mise activate利用時は shim を介さず PATH を更新するため、コマンド呼び出し時のオーバーヘッドを抑えられる2 - ディレクトリごとに設定を切り替えられるため、プロジェクト単位で開発環境を再現しやすい
従来構成との比較
| 機能 | 従来のツール |
mise での対応 |
|---|---|---|
| バージョン管理 |
|
mise(主要言語は標準対応) |
| 環境変数管理 | direnv |
mise( envセクション) |
| タスク実行 |
|
mise run / mise tasks
|
mise が向いている・向いていないケース
- 複数プロジェクトで異なる言語・ツールバージョンを厳密に固定したい場合や、メンバー間・CI/CD 環境でタスク定義を統一したい場合に向いている
- メンバー間で完全に同じバージョンに固定したい場合は、
mise use --pin node@20で exact version を保存するか、mise.lockをコミットする運用を検討
- メンバー間で完全に同じバージョンに固定したい場合は、
- 常に最新版のツールをシステム全体で使い続けたい場合(Homebrew 等で十分な場合)や、バイナリが配布されていないマイナーな環境には向いていない
実際に動かしてみる
導入手順
インストールはコマンドを実行するだけで完了します。
macOS の場合は Homebrew でサクッと入ります。
brew install mise
Linux や Windows など、その他の OS でのインストール方法、あるいは Zsh 以外のシェルを使う場合の設定手順については、公式の手順をご参照ください🙏
インストール後、シェルにフックを登録します。
私は Zsh を使っているので、以下を実行して ~/.zshrc に追記しました!
echo 'eval "$(mise activate zsh)"' >> ~/.zshrc
追記が完了したら source ~/.zshrc を実行するか、新しくターミナルを開き直します。正常に設定できたかは mise doctor で確認できます。
シェルフック登録時の注意点
mise は環境変数や PATH の設定を書き換えることで動作します。
他の PATH 設定によって mise の設定が上書きされるのを防ぐため、この activate コマンドは最後に追記推奨です🙏3
mise.toml の設定例
プロジェクトのルートに mise.toml を作成します。
以下は記述例です。
[tools]
node = "20.11.0"
python = "3.11.6"
[env]
APP_ENV = "development"
_.file = ".env"
[tasks.build]
run = "npm run build"
sources = ["src/**/*.ts"]
outputs = ["dist/**/*.js"]
[tasks.test]
run = "npm test"
depends = ["build"]
上記の mise.toml では、プロジェクトで使うツール、環境変数、タスクをまとめて定義しています。
| 設定 | 役割 |
|---|---|
[tools] |
プロジェクトで使用するツールとバージョンを指定 |
node = "20.11.0" |
Node.js 20.11.0 を使用 |
python = "3.11.6" |
Python 3.11.6 を使用 |
[env] |
プロジェクト内で有効にする環境変数を定義 |
APP_ENV = "development" |
APP_ENV を development に設定 |
_.file = ".env" |
.env ファイルから環境変数を読み込む |
[tasks.build] |
build タスクを定義 |
sources / outputs
|
入出力ファイルの更新日時をもとに、不要な再実行をスキップ |
[tasks.test] |
test タスクを定義 |
depends = ["build"] |
test の前に build を実行 |
この状態で mise install を実行すると設定したツールがインストールされます。
シェルフックが有効になっていれば、以降はディレクトリに入るだけで自動で有効化されます。
また、初回読み込み時に mise trust による許可を求められた場合は、内容を確認して実行します。
ここで便利なのが、mise の内蔵タスクランナーです。例えば、先ほどの設定なら以下で build → test の順に実行できます。
mise run test
mise run で実行したタスクには、mise.toml で定義したツールや環境変数も反映されます。
-
dependsを使うと、依存するタスク(例:build)を自動で事前実行できる -
sourcesとoutputsを指定すると、出力ファイルが入力ファイルより新しい場合にタスクの再実行をスキップできる
mise.toml は Git で共有し、機密情報の入った .env などは必ず .gitignore で除外しましょう!
API キーなどの値そのものは共有せず、必須の環境変数だけを定義したい場合は、以下のように required = true を使えます。
[env]
DATABASE_URL = { required = true }
開発をさらに便利にする Tips
最後に、mise の便利な Tips をいくつか紹介します!
1. グローバル設定の活用
すべてのプロジェクトで共通して使いたいデフォルトバージョンは、グローバル設定ファイルに記述しておくと便利です!
以下のコマンドで、グローバル設定ファイルを直接編集できます。
mise edit ~/.config/mise/config.toml
例えば、以下のように書いておけば、プロジェクト固有の設定がない場所では常に LTS 版の Node.js が使われます。
[tools]
node = "lts"
2. エコシステムを明示したインストール
npm registry の CLI ツールを mise で管理したい場合、プレフィックスをつけて指定できます。
# npm registry から prettier をインストール
mise use npm:prettier
これによってインストールしたツールは、mise が自動的に実行ファイルの場所を PATH に追加してくれるため、プロジェクトディレクトリ内でそのまま prettier コマンドを実行できるようになります。
package.json の開発依存関係(devDependencies)やグローバル環境を汚さずに、プロジェクト専用のツールを用意できるため非常に重宝します!
3. CI などの非対話環境での実行
CI やスクリプト環境など mise activate を使わない場所では、mise x -- <command> や mise run <task> を使うと、シェルフックに依存せず mise の環境を明示的に読み込んで実行できます。
# 一時的に指定したバージョンでコマンドを実行する例
mise x node@20 -- npm test
なお、IDE や非対話環境向けには mise activate --shims も利用できますが、通常の mise activate とは仕組みが異なるため、[env] の環境変数や hooks を含めて完全に同じ挙動になるとは限りません。
4. node_modules/.bin への自動パス通し
mise.toml に以下の環境変数設定を追加すると、プロジェクトローカルの node_modules/.bin に自動的にパスが通ります。4
これにより、npx を介さずにローカルインストールされた CLI ツール(tsc や vite など)を直接実行できるようになります!
[env]
_.path = ["{{config_root}}/node_modules/.bin"]
おわりに
読んでいただきありがとうございます🙏
Qiita Tech Festa で選んだ水派にちなんで、よく使っている mise について書いてみました💧
mise を導入すると、バージョン管理・環境変数・タスク定義を mise.toml に一元管理できます。
複数ツールの管理に悩んでいる方は、ぜひ一度試してみてください!
参考
-
公式発音はミーズ(meez)。料理用語の mise en place が由来で、包丁を研ぎ、食材を刻み、作業台を整えるといった「本番の仕事の前にする準備作業」を意味します。 https://mise.jdx.dev/ ↩
-
mise 公式の asdf 比較ページでは、asdf の shim は runtime call ごとに約120msのオーバーヘッドが発生すると説明されています。 https://mise.jdx.dev/dev-tools/comparison-to-asdf.html ↩
-
PATH の優先順位で問題が出る場合は、公式ドキュメントの
mise activateや shell integration の説明を確認してください。環境やシェル設定によって対処が異なります。 ↩ -
{{config_root}}を使うと、プロジェクトルート基準のパスであることを明示できます。なお、mise の環境ディレクティブ内の相対パスも基本的にはconfig_root基準で解決されます。 https://mise.jdx.dev/environments/ ↩