--prefer-dist并非强制下载压缩包,而是优先使用HTTPS ZIP/TAR包,无有效dist.url时静默回退source;需通过-v日志、.git缺失及composer show -s验证是否生效。

CI里还在git clone vendor包?先确认--prefer-dist是否真生效
加了--prefer-dist却卡在Cloning into 'vendor/xxx',大概率不是参数没写对,而是根本没走dist模式。验证必须看实际行为,不能只盯命令行:
- 加
-v运行:composer install -v,输出中出现Downloading https://.../archive/且无Cloning或git clone字样才算真正生效 - 检查
vendor/xxx目录:没有.git文件夹,基本可断定是dist模式;有.git就一定是source - 运行
composer show -s vendor/package:看dist字段是否非空,且url是HTTPS ZIP/TAR链接(不是git@github.com:这类SSH格式)
为什么加了--prefer-dist还是git clone
这不是参数失效,而是Composer自动fallback——因为dist条件不满足:
- 依赖约束写的是
"dev-main"或"dev-master",没打正式tag,Packagist就无法生成dist信息 -
composer.json里该包被显式设为"source": {},且没配对应dist - 本地
vendor/xxx已存在且是source模式,而composer.lock未更新,Composer复用旧目录 - 设置了环境变量
COMPOSER_PREFER_SOURCE=1,它优先级高于命令行参数 - 私有包没在仓库配置archive,或没发布GitHub Release,导致
dist.url为空
CI脚本里怎么稳住--prefer-dist不 fallback
靠每次加参数不够可靠,项目级或全局配置更可控:
- 项目级控制(推荐):在
composer.json的config段加"preferred-install": { "*": "dist" },比每次敲命令更稳定 - 混合策略(最实用):
"preferred-install": { "myorg/*": "source", "*": "dist" },自家私有包保留git,第三方全走压缩包 - CI脚本中组合使用:
composer install --prefer-dist --no-dev --optimize-autoloader,三者配合压榨效率 - 注意通配符顺序:
"*": "dist"必须放在最后,否则会覆盖前面的规则;匹配是按包名前缀,"monolog"不匹配monolog/monolog,得写"monolog/"
CI镜像没装git时别硬补,直接切dist模式
Docker镜像(如php:alpine)默认不带git,apt-get install git只是临时补救,不如直接切回--prefer-dist:
- dist模式走HTTPS下载,只要能通Packagist或GitHub Releases即可,不依赖
git命令或SSH - source模式强依赖git可用、远程仓库可连、认证通过,CI中卡住90%是因为缺Git或SSH key
- 如果必须用source(比如调试私有包),确保构建机已配好SSH key或GitHub token,并允许访问
git@github.com或对应端口 - 换国内镜像源后务必执行
composer clear-cache,否则旧源还在内存里苟着
真正容易被忽略的是:composer.lock里记录的安装方式会直接影响下次install行为。哪怕你配了preferred-install,已有vendor目录也不会自动重装——必须删掉再跑一次composer install才能生效。











