使用 mise 替代 asdf 管理开发工具的版本
前言
一直以来我都使用 asdf 管理开发环境各工具链的版本,它可以让每一个项目都允许拥有自己的一套版本,不会因为依赖全局性的东西导致额外的负担(例如系统中的工具版本变更导致和项目不兼容)。
在最近我接触到 mise
,并最终决定用它取代 asdf
。倒不是因为 asdf
不好,是因为 mise
更好。
用途
asdf
或 mise
。你完全可以不同意这些观点。使用 asdf
有以下几个理由:
- 你的项目进展不一,对应的开发环境版本不一致。例如 A 项目最近还在维护,它有可能升级到最新的工具版本(如 Java 18)。但 B 项目是 10 年前的,它最多基于当时的 Java 8。
- 你总是想使用自己的版本,摆脱系统软件源。例如各 Linux 发行版的软件源会根据自己的计划来维护软件包的版本,他们的频率和你可能并不一致。例如他们决定半年后升级到最新的 Java 大版本,但你现在就想用(或不想升级)。摆脱 Linux 发行版软件源中的开发工具,是将 Linux 作为开发环境时非常基本的前提。
有时候这些理由不适用你的场合。例如你使用的开发工具非常成熟,发展已渐缓。几年可能都不会有什么明显动静。这种情况下,确实是不重要了。就像我们编译大量 C/C++ 开源软件时甚至可以用各种版本跨度的编译器。
如果你使用的是一些更激进的开发语言,它们的版本发布非常快,经常推陈出新(淘汰各种旧 API)。那就有很大的必要性了。
相同点
mise
可以无缝替代 asdf
,因为它具有 asdf
的一切功能。实际上 mise
默认把 asdf
作为后端,可以直接使用 asdf
的所有插件生态。
命令行使用
在 asdf
中,我们通过命令添加插件,然后安装插件对应工具的各种版本:
asdf plugin-add elixir # 添加 Elixir 插件
asdf install elixir 1.16.2-otp-26 # 安装指定的 Elixir 版本
上述过程在 mise 中是一个操作:
mise use elixir@1.16.2-otp-26
mise 会自动完成 Elixir 的插件和版本安装。
配置文件使用
在 asdf
中,会默认加载当前目录下的 .tool-versions
文件。这是一种十分简洁的 K/V 文本,如下:
erlang 26.2.5
elixir 1.16.2-otp-26
在 mise
中则使用了更为复杂 toml
格式,命名为 .mise.toml
。如下:
[tools]
erlang = "26.2.5"
elixir = "1.16.2-otp-26"
上述两个文件定义的配置是完全等同的。mise
会像 asdf
自动加载 .tool-versions
文件那样,默认加载 .mise.toml
文件。
优势
mise
除了完全兼容 asdf
以外,还进行了一些扩展,功能和使用体验增强。
兼容旧配置
mise
兼容 .tool-versions
文件,并且也会默认加载它。所以切换到 mise
以后甚至可以不用改动什么,是一种无缝无感的过渡。若需要 .tool-versions
无法实现的功能,则可以开始用 .mise.toml
取代。
更为自动化
使用 asdf
时若 .tool-versions
中的版本并未安装,调用这些工具会得错误提示。然后由用户手动执行 asdf install
才能正常使用。
mise
在这方面提高了使用体验:当发现配置的版本未安装,会自动执行安装过程,然后再执行用户的原始命令。
传递选项
mise
可以通过 .mise.toml
配置向工具传递选项。例如给 Python 传递虚拟环境的目录:
[tools]
python = { version = '3.10', virtualenv = '.venv' }
这样我们就不需要每次都手动执行激活命令。
作为包管理器
mise 不仅仅可以安装各语言的基础工具链,甚至还可以管理某些语言的依赖包的版本。例如著名的十分全能的格式化工具 prettier
,它是使用 JS 实现的 NodeJS 运行时的软件包,通常需要 NPM 来管理。
但我们可以这样配置:
[tools]
"npm:prettier" = "latest"
让 mise 来管理 Prettier 的安装和版本,然后直接在命令行使用它。一般我们会在 package.json
中将它作为依赖,然后添加 scripts
来调用。而 mise 适用于在不包含 Web 前端的项目上使用这些 NPM 软件包。
你甚至还可以将 Hugo(本博客基于 Hugo)交给 mise 管理:
[tools]
"go:github.com/gohugoio/hugo" = "0.128.0"
不仅仅是管理 NPM/Go 的包,它还有其它支持的后端。
更多功能
mise 可以在配置中预定义环境变量,自定义插件的 URL(仓库)。自身还提供了大量可配置的定制选项。更多可以参考官方文档。
细心的你可能会发现 mise
这一个工具可以同时替代好几个工具。
清理缓存
有时候 mise 不总是会列出最新的远程版本,例如作为 npm 包管理的时候:
mise ls-remote npm:pnpm
如果你之前使用过这条命令,那么下次执行可能会看到以前的 pnpm
版本列表,缺少最新的版本。我们可以使用 mise cache clear
主动清理缓存,再次执行命令便会看到最新结果。
结束语
mise
是一个用 Rust 实现的工具,不难看出在设计上也借鉴了 Rust 自身的一些使用逻辑。例如和 Cargo 同样的配置格式,能自动化执行就不去指导用户手动执行。
从 asdf
到 mise
不仅没有切换成本还能带来更高的便利性。总的来说,十分推荐。
订阅频道第一时间掌握作者博客的最新动态,获取更多的分享。