缓存未命中或未启用是重复下载的根本原因;执行composer install --verbose,若输出为Downloading而非Downloading (cached),即表明缓存失效,即使~/.composer/cache/files/非空。

重复下载的根本原因不是缓存没开,而是缓存没被命中或根本没用上——composer install 时看到 Downloading 而非 Downloading (cached),就说明缓存失效了。
怎么确认缓存是否真在工作
执行 composer install --verbose,盯着输出里每条包的下载行:
- 出现
Downloading (cached)或Cloning (from cache)→ 缓存命中 - 只有
Downloading或Cloning→ 缓存未生效,哪怕~/.composer/cache/files/目录不为空
常见干扰项:
-
dev-master、dev-develop或带@dev的版本约束,强制跳过文件缓存,走 VCS 克隆 - 本地修改了
composer.json中的repositories,导致 VCS 缓存 key 变更,旧克隆被弃用 - CI 环境没挂载
~/.composer/cache,每次都是全新目录,缓存形同虚设
为什么加了 --no-cache 还是慢
--no-cache 确实禁用了 Composer 自身的三层缓存(files/repo/vcs),但它不解决根本瓶颈:网络延迟、PHP 解析开销、autoload 生成耗时。真正拖慢的往往是这些:
- Xdebug 启用状态:会让
composer install变慢 3–5 倍,用php -d zend_extension= composer install临时关闭 - 没切国内镜像源:默认
packagist.org在国内不稳定,执行composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/后务必composer clear-cache清旧缓存 - 漏掉
--prefer-dist:不加这个参数,即使缓存里有 ZIP 包,Composer 仍可能 fallback 到git clone,彻底绕过文件缓存
CI/CD 中缓存复用失败的硬伤点
GitHub Actions 或 GitLab CI 里写个 cache: paths: [vendor] 就以为搞定?远远不够。关键陷阱在:
- 只缓存
vendor/,不缓存~/.composer/cache/→ 下次构建时composer install仍要重新下载 ZIP 包并解压 - cache key 没包含
composer.lock哈希 → lock 文件微小变更(如时间戳)就导致缓存 miss,推荐用${{ hashFiles('**/composer.lock') }} - 不同 PHP 或 Composer 版本混用缓存 → Composer 2.5 生成的缓存不能被 1.x 读取,key 中应加入
php-${{ matrix.php-version }} - 私有包没预置认证 → 即使缓存存在,VCS 克隆阶段因
COMPOSER_AUTH缺失而失败,回退到重拉
离线安装必须跨过的三道坎
--offline 不是“打开就离线”,它极其严格,失败即终止。要让它跑通,必须提前满足:
- 缓存中 ZIP 文件的路径必须严格匹配
composer.lock里的dist.shasum字段:例如~/.composer/cache/files/vend/pack/abc123.zip必须存在且校验和一致 - 所有依赖(含私有仓库)的元数据已缓存 → 先联网跑一次
composer install --no-dev --prefer-dist,再清掉网络相关配置 - 项目中不能含
path类型仓库以外的动态源(如package或未注册的vcs),否则--offline直接报Repository not found
最易忽略的是:缓存目录本身是否在 SSD 上。如果 cache-dir 挂在 NFS 或低速 Docker volume,解压 ZIP 和读取元数据的 I/O 延迟会吃掉全部缓存收益。











