改了镜像还拉不到新包,主因是配置未真正生效或被项目级repositories覆盖;需验证composer config -g repo.packagist输出为完整json,且用--refresh强制刷新15分钟缓存的元数据。

为什么改了镜像还拉不到新包?先确认真正生效的源
很多人执行完 composer config -g repo.packagist 就以为万事大吉,结果 composer update 依然卡在 Loading composer repositories。根本原因是配置没真正写进去,或者被项目级设置覆盖了。
必须手动验证:
- 运行
composer config -g repo.packagist,输出必须是完整 JSON,形如{"type": "composer", "url": "https://mirrors.aliyun.com/composer/"};若为空、null、或仍是https://packagist.org,说明失败 - 键名只能是
repo.packagist(单数repo),写成repos.packagist会静默失败 - 如果项目根目录有
composer.json且含"repositories"字段,全局配置直接失效;此时要查composer config repo.packagist(不带-g)
同步“慢”不是镜像问题,而是本地元数据缓存没刷新
阿里云、腾讯云等主流镜像同步延迟通常在 1–5 分钟,所谓“不同步”,90% 是 Composer 复用本地旧的 packages.json 导致的——它默认 15 分钟内不重拉元数据,哪怕镜像站早已更新。
composer clear-cache 对此几乎无效:它只删 ZIP 包和部分 provider-*.json,但决定“有没有这个包”的核心元数据文件(packages.json)仍躺在 ~/.composer/cache/repo/https---mirrors-aliyun-com-composer/ 这类路径下。
正确做法:
- Composer ≥ 2.5:
composer update --refresh—— 精准丢弃所有缓存的元数据文件,强制从当前配置镜像源重拉packages.json和provider-*.json,不重下 ZIP 包 - Composer rm -rf $(composer config --global cache-dir)/repo/https---mirrors-aliyun-com-composer
- 调试时加
--no-cache -v,看终端输出的真实请求 URL 是否命中你配的镜像地址
别信 composer diag,它根本不测你配的镜像
composer diag 默认只连 https://packagist.org,完全无视你配置的任何镜像地址。它报 Connection failed,只说明本地 PHP 环境(curl、OpenSSL、系统时间)可能异常,不代表阿里云/腾讯云镜像挂了。
要验镜像是否真通、真新,得自己动手:
- 用
curl -I https://mirrors.aliyun.com/composer/packages.json,必须返回HTTP/2 200;403、404、超时都说明不可用 - 打开浏览器对比官网和镜像站同包地址,例如
https://packagist.org/packages/topthink/frameworkvshttps://mirrors.aliyun.com/composer/p/topthink/framework.json,看版本号是否一致 - 镜像站返回 404 但官网已有新版 → 同步卡住(超 30 分钟未更新属异常),不是你本地问题
项目里想兜底?双源写法有且仅有一种合法结构
Composer 不支持“多级镜像”或自动 fallback。所谓主备,本质是服务端能力(如腾讯镜像站自带 503 自动回源),客户端连超时重试都没有。
唯一被 Composer 2.9+ 稳定支持的“双源”写法,必须严格满足三点:
- 写在项目级
composer.json根节点,不能放repositories里 -
"packagist.org": false必须存在,且是布尔值false -
"repositories"数组中第一个是镜像源,第二个是官方源,末尾必须补上{"packagist": true}条目(注意不是"packagist.org")
完整示例:
{
"repositories": [
{"type":"composer","url":"https://mirrors.aliyun.com/composer/"},
{"type":"composer","url":"https://packagist.org/"},
{"packagist": true}
],
"packagist.org": false
}
注意:顺序即优先级,但 Composer 对每个源单独计时,默认 http.timeout = 30,DNS 卡住或 TLS 握手慢也会白等 30 秒才切下一个源。











