跳转到正文
YGJoon 技术博客

Flutter 使用 Melos 管理多包项目

发布于:
·1.8k 字 · 约 4 分钟·作者:
用 Melos 管理 Flutter 单仓多包:统一安装依赖、一条命令给所有子包跑静态检查和测试,附带版本号联动发布的流程
Flutter 使用 Melos 管理多包项目文章封面
目录

简介

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

最佳实践

  1. 包组织:按”发布边界”拆包,不按文件夹层级
    • 会独立发版、独立定版本的才值得成包;3 个包以下、没有发版需求时 Melos 是纯 overhead,path 依赖直连就行(本文实战案例也是这个结论)
    • 拆包前先画依赖方向:出现循环依赖(A→B→A)melos bootstrap 直接失败;用 melos list 看依赖图确认无环再动手
packages/
├── core/           # 核心功能:被所有包依赖,自己不依赖业务包
├── ui/             # UI 组件:只依赖 core
└── features/       # 业务功能:依赖 core + ui,不被其他包依赖
    ├── auth/
    └── profile/
  1. 版本控制:对外发版才用 melos version,内部包排除在外
    • linkToCommit: true 把版本号写进 git 记录,方便按版本回查问题
    • CHANGELOG 靠 conventional commits(feat:/fix:)自动生成——提交信息不规范,生成的 changelog 就是一堆乱码
    • example/demo 这类内部包用 ignoredPackages 排除在发布外,别让它占一个 pub.dev 版本号
## 更新版本并生成更新日志
melos version --graduate \
  --changelog-path CHANGELOG.md
  1. 依赖与脚本:版本在根目录统一约束,命令收进 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

注意事项

  1. bootstrap 不是免费的:包越多、依赖越重,melos bootstrap 越慢;CI 里缓存 ~/.pub-cache 和构建产物,否则每次全量 pub get 几分钟起步——本地 bootstrap 一次、CI 每次全量是最常见的 CI 变慢原因。

  2. 并发数按机器调:melos exec -c 1 的 -c 是并发包数,4 核 CI 上调到 4 能把 analyze/test 时间砍半;但 --fail-fast 在并发下某个包失败会直接中断其余包——排查问题时关掉 fail-fast,先看全量错误再修。

  3. publish 前必跑 —dry-run:检查 ignoredPackages 是否真把 example 包排除了、版本号是否已 bump;pub.dev 上发错版本删不掉(只能撤回或发新版),发版是单向操作,dry-run 是最后一道闸。

  4. 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,我们可以提高开发效率,简化版本管理,实现更好的代码复用。在使用过程中,需要注意包的划分、依赖管理和版本控制等问题,确保项目的可维护性和可扩展性。


分享这篇文章:


相关文章

上一篇
Flutter集成地图服务
下一篇
Flutter集成社交平台登录