起因
机器上同时维护 4 个项目:
- 一个 Node 16 老仓库
- 一个 Node 20 新项目
- 一个 Python 3.9 后端
- 一个 Python 3.12 数据 pipeline
之前装了 nvm + pyenv + rbenv + goenv。每个工具一套 shell hook,
shell 启动时间 1.5 秒(全是 PATH 操作)。切项目时 nvm use pyenv shell
排队按。
mise(前身 rtx)一个工具管所有语言版本,shell 启动只加 50ms。
安装
# 一行装
curl https://mise.run | sh
# 或包管理器
brew install mise
sudo apt install mise
# 装完接到 shell
echo 'eval "$(mise activate bash)"' >> ~/.bashrc
echo 'eval "$(mise activate zsh)"' >> ~/.zshrc
echo 'mise activate fish | source' >> ~/.config/fish/config.fish
mise --version
装语言
# 全局装版本
mise use --global node@20
mise use --global [email protected]
mise use --global [email protected]
mise use --global rust@stable
# 在某项目目录里指定(写入 .mise.toml 或 .tool-versions)
cd ~/projects/legacy-app
mise use node@16 # 这个目录用 Node 16
cd ~/projects/data-pipeline
mise use [email protected]
# 自动切换:cd 进目录 mise 自动 use 对应版本
.mise.toml 项目配置
# .mise.toml
[tools]
node = "20"
python = "3.12"
go = "1.22"
rust = "stable"
"npm:pnpm" = "latest" # 通过 npm 装 pnpm
"pipx:poetry" = "latest" # 通过 pipx 装 poetry
"go:github.com/jesseduffield/lazygit" = "latest"
[env]
DATABASE_URL = "postgresql://localhost/myapp"
PYTHONDONTWRITEBYTECODE = "1"
[tasks.test]
description = "Run tests"
run = ["pytest", "npm test"]
[tasks.dev]
description = "Start dev server"
run = "npm run dev"
之后:
mise install # 装 .mise.toml 声明的所有工具
mise run test # 跑 [tasks.test]
mise run dev
mise tasks # 列所有 tasks
列出 / 切换
mise ls # 看当前激活的工具版本
mise ls --installed # 看本机装了哪些版本
mise outdated # 看哪些工具有新版本
mise current # 当前目录最终生效的版本(含继承)
mise where node # 当前 node 二进制路径
env 管理
mise.toml 的 [env] 段在 mise activate 后 cd 进目录自动注入:
[env]
AWS_PROFILE = "dev"
DATABASE_URL = "postgresql://localhost/myapp"
_.path = ["./bin", "./node_modules/.bin"] # 加 PATH
_.file = ".env" # 也读 .env 文件
替代了 direnv 大部分用法。
与 .tool-versions(asdf 兼容)
asdf 用户已有 .tool-versions:
nodejs 20.10.0
python 3.12.1
ruby 3.2.0
mise 直接读,零迁移。新项目也建议用更强大的 .mise.toml 格式。
团队协作
把 .mise.toml 进 git:
git add .mise.toml
git commit -m 'chore: pin tool versions via mise'
新人 clone 后:
cd repo
mise install # 装齐所有工具版本
CI 里:
- uses: jdx/mise-action@v2
with:
cache: true
- run: mise run test
性能对比
| 启动延迟 | 多语言 | |
|---|---|---|
| nvm | 500-1500ms | ❌ |
| pyenv | 200-400ms | ❌ |
| asdf | 200-500ms | ✅ |
| mise | 30-50ms | ✅ |
Rust 写的 + 智能 PATH shim 让启动几乎瞬时。
替代了什么
机器上以前装的:
- nvm → 删
- pyenv → 删
- rbenv → 删
- goenv → 删
- direnv(大部分用法)→ 删(保留给复杂 shell 逻辑)
.zshrc 从 80 行清到 30 行,shell 启动 1.5s → 0.2s。
mise tasks vs Makefile
mise tasks 比 Makefile 优势:
- 不需要 tab 缩进
- 跨平台一致(make 在 Windows 不友好)
- 自动激活该项目的工具版本
- TOML 比 Makefile 易读
[tasks.lint]
run = ["ruff check .", "mypy src/"]
[tasks.fmt]
run = ["ruff format .", "ruff check --fix ."]
[tasks.ci]
depends = ["lint", "test"]
run = "echo all green"
[tasks.test]
run = "pytest --cov"
mise run ci # 自动跑 lint + test
效果
- 4 个项目切换无感(cd 进去自动切版本)
- shell 启动 < 0.2s
- 一个工具管所有语言:心智模型干净
- .mise.toml 进 git 让新同事 onboard "git clone + mise install" 完事
- task runner 顺带替代了一半 Makefile / package.json scripts
踩过的坑
-
从 nvm 迁过来 PATH 顺序乱:nvm 残留 PATH 里。彻底清 nvm:
bash rm -rf ~/.nvm # ~/.bashrc 里删掉所有 nvm 相关行 -
mise 后台编译 Python / Ruby 慢:源码编译需要 build-essential +
libssl-dev 等系统库。Debian/Ubuntu:
bash sudo apt install -y build-essential libssl-dev libffi-dev \ libsqlite3-dev libbz2-dev libreadline-dev zlib1g-dev \ libncurses-dev liblzma-dev tk-dev -
CI 没缓存导致每次都重装:mise-action 加
cache: true。 -
某些工具用 GitHub release 装:网络问题在国内有时拉不下来。
设MISE_GITHUB_TOKEN或者镜像源。 -
VSCode Python 解释器找不到:mise 装的 Python 在
~/.local/share/mise/installs/python/3.12.0/bin/python。
.vscode/settings.json写"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python"让它用项目 venv。
登录后参与评论。