mise(前 rtx):单工具管理 Node / Python / Go / Ruby 版本

起因

每个项目用不同版本的 runtime / SDK:

  • 项目 A:Node 18 + Python 3.11
  • 项目 B:Node 20 + Python 3.12
  • 项目 C:Go 1.22 + Bun 1.1

老办法各种 version manager:

  • nvm(Node)
  • pyenv(Python)
  • rbenv(Ruby)
  • gvm / goenv(Go)

每个工具一套 shell 集成 / shim 机制 → 启动慢 + 配置碎。

mise(Rust 写的,前身 rtx,前前身 asdf 的现代 fork)是一个工具
管理所有版本
.mise.toml 文件描述项目所需版本,进目录自动切。

# macOS
brew install mise

# Linux
curl https://mise.run | sh

# 集成 shell
echo 'eval "$(mise activate zsh)"' >> ~/.zshrc

项目用

cd ~/projects/myapp

# 给项目指定 Node 20 + Python 3.12
mise use node@20 [email protected]

# 自动写到 .mise.toml
cat .mise.toml
# [tools]
# node = "20"
# python = "3.12"

# 装这俩
mise install

进入这目录 → mise 自动激活对应版本:

$ cd ~/projects/myapp
$ node --version
v20.18.0
$ python --version
Python 3.12.4

$ cd ~/projects/other
$ node --version
v18.20.0       # 自动切换

.mise.toml 完整例

# .mise.toml(项目根,commit 进 git)

[tools]
node = "20.18.0"          # 精确版本
python = "3.12"           # 主版本
go = "1.22"
bun = "latest"            # 最新
"npm:pnpm" = "9"          # 通过 npm 装 pnpm

# 环境变量
[env]
NODE_ENV = "development"
PYTHONUNBUFFERED = "1"
_.file = ".env"           # 加载 .env 文件

# 项目 task(取代 justfile / Makefile,简单场景)
[tasks.dev]
run = "node server.js"

[tasks.test]
run = "pnpm test"

mise install 装全部 → 进目录自动用。

比 asdf 快多少

mise 是 asdf 的 Rust rewrite + 改进:

asdf mise
语言 Bash Rust
shell hook 延迟 50-200ms < 5ms
工具机制 shim env-based + shim
配置 .tool-versions .mise.toml
任务系统 有(取代 just)
装速度

cd 到项目目录,asdf 的 shell hook 拖 100ms+。mise 几乎无感。

多 runtime + 同时

[tools]
node = ["20", "22"]       # 两个版本都装

# 默认用第一个 → node 是 20
# 调 22:mise exec node@22 -- node --version

共享 mise.toml + 个人 override

# .mise.toml(commit)
[tools]
node = "20"
python = "3.12"

# .mise.local.toml(gitignore,个人覆盖)
[tools]
python = "3.13"           # 我本地试 3.13

.mise.local.toml 覆盖 .mise.toml,团队不受影响。

全局默认

mise use -g node@22
mise use -g [email protected]

写到 ~/.config/mise/config.toml。没有 .mise.toml 的目录用全局
版本。

工具源

mise 用 asdf 插件 + 内置后端:

# 列出可装
mise ls-remote node
mise ls-remote python

# 通过 npm / pip / cargo 后端装
mise use "npm:typescript@5"
mise use "pipx:black@24"
mise use "cargo:ripgrep@13"

也支持 GitHub release / ubi / pre-compiled binary 等。

task runner

[tasks.lint]
description = "Run linters"
run = """
ruff check .
pnpm tsc --noEmit
"""

[tasks.test]
depends = ["lint"]
run = "pytest"
$ mise tasks         # 列出
$ mise run test      # 跑(先跑 lint)

替代 justfile 的简单场景。复杂的还是 just 强。

环境变量 + secrets

[env]
DATABASE_URL = "postgres://localhost/myapp"
_.file = ".env.local"        # 也加载这文件
_.path = ["./bin", "./node_modules/.bin"]   # 加 PATH

进目录自动 export → 写脚本不用 source。

.env.local 在 .gitignore,本地 secrets。

CI 用 mise

# GitHub Actions
- uses: jdx/mise-action@v2
  with:
    install: true
- run: mise run test

CI 装的版本 = .mise.toml 里的版本 = 本地版本。一致性保证。

与 Docker dev container 对比

mise Docker dev container
隔离 进程级 完全隔离
启动 即时 启动 container 几秒
IDE 原生(无远程) VS Code Remote
文件 IO 原生 bind mount 可能慢(mac)
生产一致性 中(runtime 一致 OS 可能不同)

小项目 / 单人 → mise 够用 + 更快。
大项目 + 多 OS 团队 → devcontainer 更靠谱。
我自己 95% 项目 mise,少数客户项目 devcontainer。

从 nvm 迁移

# 卸 nvm
rm -rf ~/.nvm
# 从 .zshrc 删 nvm source

# 装 mise + 集成

# 老的 .nvmrc 自动识别(兼容)
echo "v20" > .nvmrc
mise install

.nvmrc / .python-version / .tool-versions mise 全识别。
不强制迁到 .mise.toml,但建议(功能更强)。

踩过的坑

  1. shell 没集成node --version 返回老版本。mise 必须 shell
    hook 才能切。mise activate 加 rc 文件 + 重开终端。

  2. CI 装很慢:mise 第一次装 Python 3.12 编译几分钟。
    MISE_PYTHON_COMPILE=0 用预编译 binary(uv 同样做法)。或者
    cache ~/.local/share/mise/installs

  3. 跟 asdf 冲突:装了 asdf 又装 mise → PATH 混。卸一个。

  4. 某些工具没插件:罕见工具 mise 没现成插件。可以 mise plugin install <git-url> 加 asdf 插件用。

  5. mise use 不写版本会写 latest 到 .mise.toml:commit 进 git
    后别人装的可能是更新版本。建议明确版本号。

精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。