Composer 管理 Monorepo 的核心是主仓库不依赖子项目,子项目独立声明依赖,通过 path repository 实现本地开发联动与发布后切换真实包源;目录扁平化、根配置路径仓库、子项目规范定义 name/type/autoload、开发用 path、发布走标准流程。

用 Composer 管理 Monorepo 的核心思路是:**主仓库不直接依赖子项目,子项目各自声明依赖,通过路径仓库(path repository)在开发期本地联动,发布后切换为真实包源**。关键不在“统一安装”,而在“分治管理 + 智能复用”。
1. 目录结构设计:清晰隔离,避免嵌套冲突
推荐扁平化布局,每个子项目是独立的 Composer 包(含自己的 composer.json),不嵌套在其他项目的 vendor 或源码目录中:
- /packages/my-component —— 可复用的库,type: "library"
- /apps/my-api —— 应用项目,type: "project"
- /apps/my-admin —— 另一个应用,可复用 /packages/my-component
- /composer.json(根)—— 仅用于配置路径仓库和开发脚本,不声明业务依赖
2. 根 composer.json 配置 path repository
让所有子项目在本地开发时能被其他项目识别为可安装包:
{
"repositories": [
{
"type": "path",
"url": "packages/*"
},
{
"type": "path",
"url": "apps/*"
}
],
"require": {},
"minimum-stability": "dev",
"prefer-stable": true
}
这样,在 /apps/my-api/composer.json 中就可以写:
"my-vendor/my-component": "dev-main" —— Composer 会自动映射到 /packages/my-component 目录,软链接或复制方式取决于 --prefer-source 和配置。
3. 子项目 composer.json 必须规范定义
每个子项目需明确自身身份,便于工具识别和 CI 处理:
- 设置 "name"(如 "my-vendor/my-component"),与 Packagist 命名一致
- 声明 "type":library / project / metapackage
- 指定 "autoload" 和 "autoload-dev",支持 PSR-4
- 若为应用,加 "config": { "allow-plugins": { "...": true } } 控制插件权限
4. 日常开发与发布流程
本地开发靠 path repo 实时联动;发布时走标准流程,不破坏 Monorepo 结构:
- 改完 /packages/my-component 后,运行 composer update my-vendor/my-component --with-dependencies 更新所有依赖它的应用
- CI 中按需发布:检测 /packages/** 目录变更,自动打 tag、push 到 Packagist 或私有仓库
- 应用项目上线前,把 "repositories" 中的 path 条目注释掉,确保使用已发布的稳定版本
- 可用 composer config --unset repositories 或环境变量控制仓库源切换
不复杂但容易忽略。重点是别让根 composer.json 承担业务依赖职责,也不要把子项目当文件夹硬拷贝——用好 path repository,Monorepo 就是多个包的协作现场,不是捆绑销售的压缩包。










