monorepo 工具 moon 从 v1 到 v2 走了整整一个大版本周期,这次更新不是小修小补——工具链从硬编码变成了 WASM 插件架构,配置格式从单一 YAML 扩展到 JSON 和 TOML,CLI 命令结构全面重组,任务继承和 Docker 集成也做了大幅改造。如果你在用 moon 管 monorepo,v2 是一次架构层面的迁移;如果还没用过,现在是个值得重新评估的节点。
WASM 插件工具链:从"内置一切"到"按需加载"
v1 时代,moon 把 Node、Rust、Go 等工具链的逻辑直接写进核心代码。新增一种语言或自定义工具?等官方发版。v2 把这块彻底拆出来——工具链变成了 WASM 插件,每个插件是一个独立的 .wasm 文件,通过 moon 的插件系统加载执行。
这意味着几件事:
- 自定义工具链不再需要改 moon 本体。写一个 WASM 插件,就能让 moon 认识你的编译器、linter、格式化工具。
- 插件可以独立发布和版本管理,团队内部可以维护私有工具链插件,不依赖上游节奏。
- 加载范围可控,只注册项目实际用到的工具链,减少无关依赖的初始化开销。
插件用 Rust 或其他能编译到 WASM 的语言编写,moon 提供了插件 SDK,核心接口围绕"检测工具版本"、"解析配置"、"生成任务命令"三个动作。
配置格式:YAML 不再是唯一选择
v2 的配置文件不再绑定 YAML。.moon/config.json、.moon/config.toml 都能被直接识别,moon 会根据文件扩展名自动选择解析器。
这对不同团队的习惯是个实质改善:
- Rust 团队倾向 TOML,和
Cargo.toml风格一致,阅读成本低。 - 前端团队用 JSON 更顺手,也能和
tsconfig.json、package.json保持同源。 - YAML 仍然可用,已有项目不需要迁移。
三种格式在语义上完全等价,只是写法不同。moon 内部统一转成同一套数据结构处理。
CLI 重组与任务继承增强
v2 的 CLI 命令结构做了重新编排,最直观的变化是子命令分组更清晰——moon run、moon check、moon sync 等核心命令的参数和行为更一致,--help 输出也更可读。
更深层的变化在任务继承。v1 的任务继承规则有隐式优先级,跨项目继承时容易踩坑。v2 明确了继承链的解析顺序:项目级配置 > workspace 级配置 > 插件默认值,覆盖关系不再依赖声明顺序。
Docker 集成也做了改造——moon docker 子命令现在直接支持多阶段构建配置,不再需要手写 Dockerfile 来拼装 moon 的构建产物。
VCS 支持改进
v2 对版本控制系统(VCS)的检测更准确,尤其是在 monorepo 内嵌子仓库或使用 Git worktree 的场景。moon 现在能更可靠地判断哪些文件受 VCS 管理,从而影响 moon sync 和增量构建的范围判定。
实战:用 TOML 配置 + 自定义工具链插件跑一个项目
下面是一个可复制的最小示例,展示 v2 的 TOML 配置写法和工具链插件注册。
1. 项目结构
my-monorepo/
├── .moon/
│ ├── config.toml
│ └── toolchains/
│ └── my_custom_toolchain.wasm
├── apps/
│ └── web/
│ └── moon.yml
└── packages/
│ └── core/
│ └── moon.yml
2. Workspace 级 TOML 配置
# .moon/config.toml
[workspace]
name = "my-monorepo"
# 注册 WASM 插件工具链
[toolchain]
my_custom = { plugin = "toolchains/my_custom_toolchain.wasm" }
# 全局任务继承:所有项目默认继承这些任务
[task.default]
command = "echo 'running default task for ${project}'"
[task.lint]
command = "my_custom lint"
toolchain = "my_custom"
[task.build]
command = "my_custom build"
toolchain = "my_custom"
3. 项目级配置覆盖
# apps/web/moon.yml
project:
name: "web"
# 继承 workspace 的 lint 和 build,但覆盖 build 命令
tasks:
build:
command: "my_custom build --target=web"
toolchain: "my_custom"
deps:
- "core:build"
# packages/core/moon.yml
project:
name: "core"
tasks:
build:
command: "my_custom build --target=lib"
toolchain: "my_custom"
4. 运行构建
# 安装 moon v2(如果还没升级)
curl -fsSL https://moonrepo.dev/install.sh | bash -s -- v2
# 同步项目状态
moon sync
# 运行整个 workspace 的 build(自动按依赖拓扑排序)
moon run :build
# 只跑 web 项目的 lint
moon run web:lint
5. Docker 多阶段构建
# v2 的 docker 子命令直接生成多阶段构建镜像
moon docker scaffold --target=web
# 生成的 Dockerfile 会自动包含 moon 构建阶段和最终运行阶段
# 可以进一步编辑后构建
docker build -t my-monorepo-web .moon/docker/web.Dockerfile
注意:上面的
my_custom_toolchain.wasm是示意文件名,实际使用时需要用 moon 插件 SDK 编写并编译。如果你只是想先体验 v2 的配置格式变化,可以暂时不注册自定义工具链,先用内置的 Node/Rust 工具链跑起来。
升级与采用建议
v2 是一次架构迁移,不是改个版本号就能无缝切换。以下是实际升级时需要关注的点:
| 关注项 | 说明 |
|---|---|
| 配置格式迁移 | YAML 配置仍然可用,不需要立刻改写。但如果你团队更习惯 TOML/JSON,可以逐步替换,两种格式可以共存。 |
| 工具链插件 | 如果你用了 v1 内置的 Node/Rust/Go 工具链,v2 提供了对应的官方 WASM 插件作为替代,行为兼容。自定义工具链需要重新用 SDK 编写。 |
| CLI 命令变化 | 部分 v1 命令的参数有调整,建议跑一遍 moon --help 对照脚本中的调用。 |
| 任务继承 | v2 的继承优先级更明确,如果你的 v1 配置依赖了隐式覆盖行为,需要检查任务声明顺序是否仍然符合预期。 |
| Docker 集成 | 如果你之前手写了包含 moon 步骤的 Dockerfile,可以评估是否迁移到 moon docker 子命令来减少手动维护。 |
升级路径:先在非生产分支跑 moon sync + moon run :build,确认任务拓扑和继承行为无误,再合并到主线。配置格式可以分项目逐步迁移,不必一次性全改。
moon v2 的核心信号是——monorepo 工具不应该把语言支持和构建逻辑锁死在核心代码里。WASM 插件打开了自定义空间,多格式配置降低了团队摩擦,CLI 重组让日常操作更可预测。如果你在 monorepo 构建上碰过"工具不支持我的语言"或"配置格式和团队习惯不一致"这类墙,v2 值得认真试一轮。