简介
Melos 是一个用于管理 Dart/Flutter 多包项目(monorepo)的工具,它提供了强大的工作空间管理、版本控制和发布功能。本文将详细介绍如何使用 Melos 来管理 Flutter 多包项目。
基本配置
安装 Melos
## 全局安装 melos
dart pub global activate melos
## 验证安装
melos --version
初始化项目
## 创建新项目
mkdir my_monorepo
cd my_monorepo
## 初始化 melos
melos init
melos.yaml 配置
name: my_monorepo
packages:
- packages/**
- apps/**
command:
version:
# 确保所有包使用相同的版本号
linkToCommit: true
bootstrap:
# 运行 pub get 之前的钩子
hooks:
pre: |
dart pub global activate melos
scripts:
analyze:
# 分析所有包
run: |
melos exec -c 1 -- \
flutter analyze .
description: Run `flutter analyze` for all packages
test:
# 运行所有测试
run: |
melos exec -c 1 --fail-fast -- \
flutter test
description: Run all tests in this project
build:
# 构建所有包
run: |
melos exec -c 1 -- \
flutter build
description: Build all packages
项目结构
my_monorepo/
├── apps/ # 应用程序
│ ├── mobile/ # 移动应用
│ └── web/ # Web 应用
├── packages/ # 共享包
│ ├── core/ # 核心库
│ ├── ui/ # UI 组件库
│ └── utils/ # 工具库
├── melos.yaml # Melos 配置
└── pubspec.yaml # 根 pubspec
包管理
创建新包
## 创建新的 Flutter 包
cd packages
flutter create --template=package my_package
## 创建新的 Dart 包
dart create -t package my_dart_package
包依赖管理
## packages/my_package/pubspec.yaml
name: my_package
version: 0.1.0
dependencies:
core:
path: ../core
utils:
path: ../utils
工作空间命令
## 初始化所有包
melos bootstrap
## 清理所有包
melos clean
## 运行特定脚本
melos run analyze
melos run test
melos run build
版本管理
版本更新
## 更新所有包版本
melos version
## 指定版本类型
melos version --graduate
melos version --preid beta
发布配置
## melos.yaml
command:
publish:
# 确保在发布前运行测试
hooks:
pre: |
melos run test
# 发布配置
ignoredPackages:
- "example*"
发布包
## 发布所有包
melos publish
## 发布特定包
melos publish --package my_package
工作流示例
开发流程
## 1. 克隆项目
git clone my_monorepo
cd my_monorepo
## 2. 初始化工作空间
melos bootstrap
## 3. 创建新功能分支
git checkout -b feature/new-feature
## 4. 开发和测试
melos run test
melos run analyze
## 5. 提交更改
git commit -m "feat: add new feature"
## 6. 更新版本
melos version
CI/CD 配置
## .github/workflows/ci.yml
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Flutter
uses: subosito/flutter-action@v2
- name: Install Melos
run: dart pub global activate melos
- name: Bootstrap workspace
run: melos bootstrap
- name: Run tests
run: melos run test
- name: Analyze
run: melos run analyze
最佳实践
- 包组织:按”发布边界”拆包,不按文件夹层级
- 会独立发版、独立定版本的才值得成包;3 个包以下、没有发版需求时 Melos 是纯 overhead,path 依赖直连就行(本文实战案例也是这个结论)
- 拆包前先画依赖方向:出现循环依赖(A→B→A)
melos bootstrap直接失败;用melos list看依赖图确认无环再动手
packages/
├── core/ # 核心功能:被所有包依赖,自己不依赖业务包
├── ui/ # UI 组件:只依赖 core
└── features/ # 业务功能:依赖 core + ui,不被其他包依赖
├── auth/
└── profile/
- 版本控制:对外发版才用 melos version,内部包排除在外
linkToCommit: true把版本号写进 git 记录,方便按版本回查问题- CHANGELOG 靠 conventional commits(
feat:/fix:)自动生成——提交信息不规范,生成的 changelog 就是一堆乱码 - example/demo 这类内部包用
ignoredPackages排除在发布外,别让它占一个 pub.dev 版本号
## 更新版本并生成更新日志
melos version --graduate \
--changelog-path CHANGELOG.md
- 依赖与脚本:版本在根目录统一约束,命令收进 scripts
- 第三方依赖版本全仓统一(workspace/dependency_overrides),避免 5 个包各锁一个 dio 版本、bootstrap 后出现运行时类型冲突
- analyze/test/build 收进 melos.yaml 的 scripts,CI 里只调
melos run xxx——保证本地和 CI 跑的是同一套命令,本地过了 CI 挂的扯皮直接消失
## packages/feature/pubspec.yaml
dependencies:
core:
path: ../core
ui:
path: ../ui
常见问题
1. 依赖冲突
## 检查依赖冲突
melos exec -- flutter pub deps
## 解决冲突
melos clean
melos bootstrap --force
2. 版本同步
## melos.yaml
command:
version:
linkToCommit: true
synchronize: true
3. 发布失败
## 检查发布状态
melos publish --dry-run
## 强制发布
melos publish --force-publish
注意事项
-
bootstrap 不是免费的:包越多、依赖越重,
melos bootstrap越慢;CI 里缓存~/.pub-cache和构建产物,否则每次全量 pub get 几分钟起步——本地 bootstrap 一次、CI 每次全量是最常见的 CI 变慢原因。 -
并发数按机器调:
melos exec -c 1的-c是并发包数,4 核 CI 上调到 4 能把 analyze/test 时间砍半;但--fail-fast在并发下某个包失败会直接中断其余包——排查问题时关掉 fail-fast,先看全量错误再修。 -
publish 前必跑 —dry-run:检查
ignoredPackages是否真把 example 包排除了、版本号是否已 bump;pub.dev 上发错版本删不掉(只能撤回或发新版),发版是单向操作,dry-run 是最后一道闸。 -
workspace 和 melos.yaml 二选一:Dart 3.6+ 的根 pubspec workspace 配置和 melos.yaml 两种写法别混用——新项目跟官方走 workspace,老项目 melos.yaml 也能用,混用会出现依赖解析打架;选定一种全仓统一。
实战案例
说实话,Melos 这个场景我还没在自己的项目里真正遇到——我手里的项目都还是单包结构。但按 Melos 官方文档的说法,它正是为 FlutterFire 这种多包仓库设计的:自动版本管理、changelog 生成、pub.dev 发布、本地包 link,一套命令管所有包。我研究下来取舍很清楚:包少于 3 个、没有发布需求时,Melos 是纯 overhead,直接用 path 依赖就行;一旦开始拆 core/ui/features、多人协作、要发版,melos bootstrap + melos exec 统一跑 analyze/test 的价值就出来了。另外注意官方文档已更新:新版推荐把 workspace 配置直接写在根 pubspec.yaml(Dart 3.6+ workspaces),melos.yaml 的写法依然可用,但新项目建议跟官方走。
参考:Melos 官方文档(Invertase)与 pub.dev 上的 melos 包说明
总结
Melos 是一个强大的多包项目管理工具,它可以帮助我们更好地组织和管理 Flutter 项目。通过合理使用 Melos,我们可以提高开发效率,简化版本管理,实现更好的代码复用。在使用过程中,需要注意包的划分、依赖管理和版本控制等问题,确保项目的可维护性和可扩展性。
