答案是必须将repositories设为数组且首项为{"packagist.org": false},并删除vendor和composer.lock后重装;否则镜像仅影响元数据拉取,lock中原始dist URL仍指向packagist.org导致下载失败。

为什么改了 composer.json 还是从 packagist.org 下载
因为 repositories 字段没写对结构:它必须是数组,且第一项必须是 {"packagist.org": false}。如果写成对象(比如 "repositories": {"packagist": {...}}),Composer 2.2+ 会直接忽略整个字段;如果漏掉 "packagist.org": false 或把它放在第二项之后,Composer 仍会 fallback 到官方源——你看到的 “Loading composer repositories” 卡住、404 或超时,基本都源于此。
正确的 repositories 数组怎么写
打开项目根目录下的 composer.json,在顶层添加或修改 repositories 字段,严格按以下顺序和格式:
"repositories": [
{"packagist.org": false},
{
"type": "composer",
"url": "https://mirrors.aliyun.com/composer/"
}
]
注意几个硬性细节:
-
url值末尾不能带/,https://mirrors.aliyun.com/composer/是错的,必须是https://mirrors.aliyun.com/composer - 私有源(如 Artifactory、Satis)要追加在镜像配置之后,保持数组顺序
- 不要合并写成
{"packagist.org": false, "type": "composer", ...}—— Composer 不认这种混写 - 如果原
composer.json已有repositories字段,先确认它是数组[]而非对象{};否则手动改成数组再插入两项
配完不清理就跑 install 必然失败
composer.lock 文件里存的是每个包原始的 dist.url(比如来自 GitHub 或 packagist.org),镜像只影响元数据(packages.json)拉取,不影响 lock 中的下载地址。所以必须执行:
rm -rf vendor composer.lock composer install
不是 composer update,也不是只删 vendor。跳过这步,你会反复看到 file could not be downloaded 或日志里持续出现 packagist.org 的请求。
怎么验证镜像真生效了
运行 composer install -vvv,滚动日志中搜索 mirrors.aliyun.com/composer/packages.json —— 如果出现且返回 200,说明元数据走镜像成功;如果还看到 packagist.org 或 api.github.com 的请求,说明 repositories 结构或清理动作仍有问题。
最容易被忽略的是:镜像只解决元数据获取,不改 lock 文件里的 dist URL。一旦项目已有 lock,哪怕配对了,也得清掉重来——这不是 bug,是 Composer 的设计逻辑。


















