composer仓库优先级遵循“命中即停”逻辑:首个返回200有效json的源胜出,后续全跳过;必须显式禁用默认源"packagist.org": false(独立项、键名精确),私有源置顶,镜像次之,确保元数据与包下载路径一致。

repositories数组顺序不是“谁先谁后”,而是“谁赢谁停”
Composer查包时,不是按数组从上到下挨个请求、等超时再试下一个;它对每个仓库发起元数据请求(如 /packages.json 或 /p2/vendor/name.json),只要某个源返回了 HTTP 200 + 有效 JSON(哪怕只是空列表或不含目标包),就立刻采用该源的响应结果,后续所有仓库全跳过。这就是「命中即停」逻辑。
常见错误是把阿里云镜像和 https://packagist.org 同时写进 repositories,且没禁用默认源——结果 Composer 总是先连原站,一断网就卡在 Could not fetch https://packagist.org/packages.json,镜像根本没机会被访问。
-
"packagist.org": false必须作为独立对象写在repositories数组末尾,不能嵌套、不能拼错键名(不是"packagist",也不是"packagist.com") - 私有仓库要优先,就得放在
repositories数组最前面——因为 Composer 是正向遍历,第一个能返回元数据的仓库胜出 - type 为
vcs的仓库(如 Git URL)不参与全局元数据匹配,只在composer require vendor/name显式调用时才触发,所以它不跟镜像抢优先级,但也不能靠它覆盖laravel/framework这类基础包
为什么禁用 packagist.org 是硬性前提
不加 "packagist.org": false,Composer 就会隐式启用官方源,并把它当作兜底项——无论你把私有源或镜像写在 repositories 多前面,它都排在最后被查。更麻烦的是:如果 packagist.org 上恰好存在同名包(哪怕只是个占位空壳),它就会返回元数据,直接终结查找流程,你的私有源永远没机会响应。
全局执行 composer config -g repos.packagist false 是危险操作,会破坏其他项目依赖安装。必须在项目级 composer.json 根层级声明 "packagist.org": false,且它必须是 repositories 数组里的一个独立项。
- 验证是否生效:运行
composer config repositories,输出中不应出现https://repo.packagist.org,且应明确看到"packagist.org": false - 如果用了
composer create-project初始化,记得删掉vendor/和composer.lock再重装——lock 文件里存的是源地址哈希,换镜像不删 lock 就白配 - type 为
package的仓库可绕过元数据匹配,但必须手动补全autoload、dist等字段,否则composer install会静默跳过
多个镜像共存 ≠ 自动 fallback
Composer 不做健康检查、不轮询、不重试。把阿里云和腾讯云镜像都写进 repositories,只要第一个(比如阿里云)服务正常,第二个就永远不会被访问。所谓“备用”,只在第一个镜像返回明确 404(包不存在)时才触发;遇到超时、500、DNS 失败,直接报错退出。
想模拟 fallback,得靠外部脚本预检可用性,例如:curl -I -s -o /dev/null -w "%{http_code}" https://mirrors.aliyun.com/composer/packages.json 返回 200 才设为当前源。否则,多写几个镜像只是徒增配置复杂度。
- 国内镜像本质是
packagist.org的只读代理,不托管私有包;混用私有源时,必须禁用默认源,否则私有包会被跳过 - 阿里云通常比腾讯云响应快,所以把它放数组第一位;但别指望第二位真能“接班”——它只在第一位明确返回 404 时才被查
- 如果镜像根索引(
/packages.json)同步延迟,新发布的包可能查不到;此时可在repositories末尾加{"packagist": true}作为元数据兜底,但 ZIP 包仍走第一个镜像下载
私有仓库 + 镜像共存的最小可靠结构
真正能跑通的组合,不是“多个源并列”,而是“分层接管”:私有源管特定包,镜像管其余公开包,官方源仅作最终元数据兜底。关键不在数量,而在位置与类型。
错误结构:repositories 里混写 https://packagist.org 和镜像 URL;正确结构是显式声明两个 type: "composer" 源,私有源放最前,镜像次之,官方源最后,并以 "packagist.org": false 收尾(注意:这个 false 项必须单独存在,不能合并)。
- 私有源 type 推荐
"composer"(需自建 Satis/Toran)或"vcs"(Git URL),避免用"package"类型——后者无法支持 dev 分支、版本别名等动态解析 - 镜像 URL 必须带完整协议和路径,如
https://mirrors.aliyun.com/composer/(结尾斜杠不能少),否则某些 Composer 版本会解析失败 - 运行
composer update -vvv vendor/name查看日志,确认Reading composer.json of行出现的是你的私有 URL 或镜像地址,而不是packagist.org
composer.lock 是否清理干净。这些地方错一个,整个优先级逻辑就失效。











