--prefer-dist 是让 Composer 优先使用预构建的 dist 归档(如 tarball),若不可用则自动回退到 source;它不强制生效,仅在有可靠 dist 且环境受限(如 CI、Docker)时才真正必要。

—prefer-dist 到底是让 Composer 干什么?
--prefer-dist 不是强制下载压缩包,而是告诉 Composer:“如果这个包提供了预构建的 dist 归档(比如 https://api.github.com/repos/monolog/monolog/tarball/2.10.0),就优先用它;如果没有,别硬来,老老实实走 source(git clone)。” 它是个“偏好”,不是开关。
背后原理很简单:Packagist 上每个包的 composer.json 会声明 dist 字段(含 URL + SHA256 校验值),Composer 拿到后直接下载、解压、校验——跳过了 git clone、git checkout、解析提交历史等全部开销。
- ✅ 有效时:下载体积小(无
.git、无测试文件)、速度快(单 HTTP GET)、不依赖 Git 环境 - ❌ 无效时:自动 fallback 到
--prefer-source行为,你完全感知不到失败——也不会报错 - ⚠️ 注意:
dev-master、dev-feature/x、path类型仓库,根本没 dist 可用,加了--prefer-dist也白搭
什么时候必须加 --prefer-dist?
不是“想快就加”,而是特定场景下加了才真正起效且必要:
- CI/CD 流水线中跑
composer install:避免反复 clone 同一仓库,省掉 Git 认证、网络超时、浅克隆配置等麻烦 - Docker 构建阶段:基础镜像常不装 Git,或容器内无 SSH key / GitHub token,
--prefer-dist是唯一能稳定安装的方式 - 只读文件系统部署(如某些 PaaS):不能写
.git目录,source 方式直接失败 - 本地首次安装大型项目(如 Laravel + 多个 SDK),且所有依赖都打了正式 tag(非 dev 分支):能明显缩短 vendor 解压前等待时间
反例:你在调试 guzzlehttp/guzzle 的某个未合并 PR,用了 "guzzlehttp/guzzle": "dev-patch-abc#commit-hash" —— 这种情况加 --prefer-dist 完全无效,Composer 会无视它。
怎么让它长期生效,又不坑自己?
全局配 prefer-dist true 看似省事,但开发机上极易翻车:
- 你顺手进
vendor/symfony/console改了行代码想提 PR?不行——没.git,git status是空的 - 想
git log -n 5看某次修复是什么时候合入的?查不了——dist 包里没历史 - 执行
composer update时,即使你没写--prefer-dist,它也默认走 dist(这是 Composer 2.2+ 的行为),你可能根本没意识到
更稳妥的做法是:
- CI 配置里显式写死:
composer install --prefer-dist --no-interaction --optimize-autoloader - 本地开发保持默认,需要临时加速时再加:
composer install --prefer-dist - 真要全局设,用项目级配置代替全局:
composer config prefer-dist true(写入当前项目的composer.json),而非-g
容易被忽略的兼容性细节
你以为加了 --prefer-dist 就万事大吉?这些点实际部署时经常卡住:
- 某些私有 Packagist(如 Satis、Private Packagist)若没正确生成并发布 dist 归档,哪怕配置了
"dist": {...},URL 返回 404,Composer 就默默切 source——而你的私有 Git 服务可能根本不可达 - PHP 8.2+ 下某些 dist 包的
autoload-dev被错误包含进生产 autoloader(因压缩包未清理 dev 文件),导致线上报Class not found—— 这和--prefer-dist无关,但现象容易误判 -
composer.lock里记录的是最终安装方式("source": {...}或"dist": {...})。如果你在 CI 里用了--prefer-dist,但本地composer update没加,lock 文件就会混着两种类型,下次别人install可能行为不一致
最保险的做法:CI 和本地都统一用 composer install(不带参数),靠 lock 文件锁定行为;只有明确知道目标包有可靠 dist 且环境受限时,才显式加 --prefer-dist。










