私有包默认不走--prefer-dist,因未显式配置dist URL,Composer只能fallback到慢的git clone;需在repositories中为私有源声明dist-url并打tag才生效。

私有包走 --prefer-dist 不是默认行为,必须显式配置 dist 信息,否则 Composer 只能 fallback 到慢得多的 --prefer-source(即 git clone)。
私有仓库为什么默认不走 dist 模式
Composer 对私有包的 dist 支持是“有条件启用”的:它不会自动为你打包或托管 zip,必须由你主动提供可下载的归档地址。官方源(packagist.org)上所有已打 tag 的公开包都自带 dist 字段;但 GitLab/GitHub 私有仓库默认不生成、也不暴露 dist URL,composer install 就只能退回去 clone 整个仓库。
- 现象:运行
composer install -vvv看到Cloning https://gitlab.example.com/xxx/yyy.git,而不是Downloading https://... - 原因:composer.json 中该包的
dist字段缺失,或repositories配置里没声明dist-url - 影响:一个未打 tag 的私有包,clone 可能耗时 30s+,而 dist 包通常 1–3s 内完成
怎么为私有包启用 dist 下载
核心动作是:在项目 composer.json 的 repositories 里,为你的私有源显式定义 dist-url 模板,并确保包本身打了 tag。
- GitLab 示例(推荐用
archiveAPI):"repositories": [ { "type": "package", "package": { "name": "myorg/my-private-lib", "version": "1.2.0", "dist": { "url": "https://gitlab.example.com/api/v4/projects/123/repository/archive.zip?sha=1.2.0", "type": "zip" } } } ] - GitHub 示例(用
releases或tarball):"dist": { "url": "https://api.github.com/repos/myorg/my-private-lib/tarball/1.2.0", "type": "tar" } - 通用技巧:用
{version}占位符,配合dist-url配置实现自动替换(需 Composer 2.2+):"repositories": [ { "type": "vcs", "url": "https://gitlab.example.com/myorg/my-private-lib.git", "dist-url": "https://gitlab.example.com/api/v4/projects/123/repository/archive.zip?sha={reference}" } ]
验证 dist 是否真正生效
不能只看命令有没有加 --prefer-dist,得查三处:
- 运行
composer install -vvv | grep "Downloading.*zip\|tar",输出中必须出现你私有源的域名和.zip或.tar.gz - 检查
vendor/myorg/my-private-lib/.git是否存在:存在 = source 模式,不存在 + 目录干净 = 很大概率是 dist - 打开
composer.lock,找对应包的dist字段:"type": "zip"且"url"是你配的私有地址,不是"type": "git"
CI/CD 中私有包提速的关键细节
很多团队在 CI 上加了 --prefer-dist 却没提速,问题常出在缓存和 lock 文件上:
-
composer.lock里若记录的是 source 安装方式,composer install会直接复用——删掉 lock 再跑composer update --prefer-dist才能写入 dist 记录 - 私有源的 dist 包 URL 必须可匿名访问(或带 token),否则 CI 会因 401 失败;建议用 GitLab Personal Access Token 或 GitHub App token 注入 URL
- 别忽略
~/.composer/cache:CI 中应缓存该目录,避免重复下载同一版本的私有 dist 包 - 如果私有包没打 tag,强制用
dev-main这类分支名,Composer 仍会 fallback 到 source——tag 是 dist 模式的硬性前提
最易被忽略的一点:私有仓库的 dist-url 模板里用了 {reference},但实际 tag 名含斜杠(如 v1.2.0),GitLab API 会 404;此时得改用 {version} 并确保 tag 名与 version 字段严格一致。


















