Composer repositories顺序错导致缓存不生效:必须将私有VCS源置顶,并以独立对象{"packagist.org": false}显式禁用官方源,否则命中即停机制会使后续配置失效。

composer.json里repositories顺序错,缓存根本不会生效
Composer 对 repositories 数组是**从上到下逐个匹配**的,一旦某个源命中了包名(比如 your-company/my-package),就立刻停止查找,后续仓库哪怕配置正确也完全被忽略。这意味着:如果你把私有 VCS 仓库写在 packagist.org 条目后面,而你的包又恰好在 Packagist 上存在同名但不同内容的废弃包,Composer 就会拉错代码——缓存里存的也是错的版本。
必须把私有 VCS 条目放在 repositories 数组最前面,并显式禁用兜底:
{
"repositories": [
{
"type": "vcs",
"url": "https://gitlab.example.com/myorg/my-package.git"
},
{
"packagist.org": false
}
]
}
-
"packagist.org": false是硬性要求,否则 Composer 在私有源未命中时仍会 fallback 到官方源(哪怕你已配阿里云镜像) - 数组不能是对象:
{"my-repo": {...}}是非法写法,会静默失败 - VCS 的
url必须指向 Git 仓库根目录(即包含composer.json的那个路径),不能是 GitHub 的网页 URL 或带/tree/main的链接
缓存目录结构不手动清理,旧 commit hash 会一直污染新安装
Composer 的 VCS 缓存默认存在 {$cache-dir}/vcs,它按远程 URL 做一级目录,再按 Git 仓库的完整 URL(含 token)哈希生成子目录。问题在于:这个缓存**不会自动感知远程分支更新或 force push**。比如你本地 dev-main 指向 commit A,缓存存了 A;后来远程 main 被 force push 成 commit B,Composer 仍可能复用 A 的缓存,导致 install 结果不一致。
解决方式不是等它自动刷新,而是明确触发清理:
- 只清特定仓库缓存:
composer clear-cache太粗暴,改用rm -rf $(composer config -g cache-dir)/vcs/*gitlab.example.com*(Linux/macOS) - CI 环境建议每次构建前加
composer clear-cache --no-interaction,避免跨流水线污染 - 若 URL 含 token(如
https://oauth2:xxx@gitlab.example.com/...),token 变更后旧缓存不会自动失效,必须手动删对应目录
HTTPS + token 认证时,缓存路径里会泄露 token 哈希
当使用 https://oauth2:<token>@gitlab.example.com/...</token> 这类嵌入 token 的 URL 时,Composer 会将整个 URL(含 token)参与哈希计算,生成缓存子目录名。虽然 token 本身不直接明文出现在路径中,但该哈希值在日志、监控或 CI 工作流输出中若被记录,理论上存在被反推风险——尤其当攻击者能控制部分 URL 字段时。
更安全的做法是绕过 URL 嵌入,改用全局凭据管理:
- GitHub:运行
composer config -g github-oauth.github.com <token></token>,URL 改回干净的https://github.com/your-org/repo.git - GitLab:运行
composer config -g gitlab-oauth.gitlab.com <token></token>,URL 保持https://gitlab.com/your-org/repo.git - 这样缓存路径只基于域名哈希,不携带认证信息,且 token 存储在
auth.json(权限必须为600)
vcs 缓存和 dist 缓存是两套机制,别指望它们互相加速
很多人以为清了 cache-files-dir 就能顺带加速 VCS 拉取,其实完全无关。Composer 的 VCS 缓存(cache-vcs-dir)只存 git clone 下来的裸仓库(.git 目录),用于快速 git checkout;而 cache-files-dir 存的是 zip/tar 包(dist),仅当包声明了 "dist" 字段才用得上。
绝大多数私有 VCS 仓库没配 dist,所以实际走的全是 VCS 流程。这时:
- 提高速度的关键是优化 Git 层:确保 Git 服务器支持 shallow clone(Composer 默认启用),并检查网络链路是否稳定
-
cache-vcs-dir大小会随私有仓库数量线性增长,定期用du -sh $(composer config -g cache-dir)/vcs监控,避免占满磁盘 - 不要试图用
--prefer-dist强制走 dist 缓存——对没提供 dist 的 VCS 包,这只会让 Composer 多发一次 404 请求再 fallback 回 git
repositories 的 JSON 结构合法性上——这些地方出错,缓存连建立的机会都没有。


















