Composer缓存生效需路径、权限、协议、key四者严丝合缝:cache-dir须本地可写且非NFS,必须启用--prefer-dist,CI中需绑定PHP版本与lock哈希的缓存key,并同步镜像源配置。

Composer install 的缓存机制不是“开了就快”,而是分层生效、必须对齐环境才能命中——多数人卡在“以为清了缓存就优化了”,实际连缓存目录都没写对或没挂载。
cache-dir 配置错,缓存根本不会写入
Composer 默认把包文件(zip/tar)和元数据(packages.json)缓存在 ~/.composer/cache,但这个路径可能被覆盖或不可写。尤其在 Docker、CI 或 root 用户环境下,cache-dir 被设为空、指向 NFS 卷、或权限不足时,缓存会静默失效。
- 运行
composer config -g cache-dir确认输出非空且路径可写(比如/tmp/composer-cache更可靠) - 若输出为空,手动设置:
composer config -g cache-dir /tmp/composer-cache - 别用
/home/www/.composer/cache这类依赖用户主目录的路径——CI 容器里该目录常不存在 - 缓存目录必须是本地 SSD 或 tmpfs,挂到网络存储(NFS/CIFS)会导致解压阶段 I/O 延迟飙升
--prefer-dist 不启用,缓存包根本不会被复用
Composer 有两个下载通道:dist(预编译 zip 包)和 source(git clone)。只有 dist 包会被写入 cache/files 并复用;source 模式每次都要 git fetch + checkout,完全绕过缓存。
-
composer install默认优先走 dist,但某些私有包或配置错误的repositories会 fallback 到 source - 强制走 dist:
composer install --prefer-dist—— 这是缓存生效的前提 - 检查是否真走了 dist:加
-v参数运行,看到Downloading https://.../package.zip才对;若出现Cloning https://.../repo.git,说明缓存没机会起作用 - 私有 GitLab/GitHub 包要确保
composer.json中声明了"dist": {"url": "...", "shasum": "..."},否则 Composer 会退化为 source 模式
CI 中只缓存 ~/.composer/cache 不够,还缺 key 对齐
CI 环境中缓存失效最常见原因不是没挂载,而是缓存 key 没和 PHP 版本、镜像源、lock 文件哈希绑定——哪怕只换一个 PHP minor 版本,缓存也会污染或不命中。
- GitHub Actions 示例中,key 应类似:
composer-${{ hashFiles('**/composer.lock') }}-${{ matrix.php-version }} - 必须同时缓存
~/.composer/cache全路径,而非只files子目录(元数据缓存repo/和 VCS 缓存vcs/同样影响首次解析速度) - 镜像源地址必须一致:若本地用阿里云,CI 里却没配
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/,缓存中的元数据 URL 不匹配,直接报Signature mismatch - 验证缓存是否命中:CI 日志里搜
Writing into cache和Cache hit,没这两句基本等于白挂
cache-files-ttl 和 cache-files-maxsize 不调,缓存会越积越多或频繁失效
默认 cache-files-ttl 是 6 个月,cache-files-maxsize 是 300MiB。在 CI 或多项目共享缓存的场景下,这两个值不调就会出问题:旧包占满空间导致新包被踢出,或长期未更新的包因 TTL 过期被清理,反而增加重下载。
- CI 场景建议调低 TTL:
composer config -g cache-files-ttl 3600(1 小时),避免跨天构建复用过期包 - 增大容量上限更稳妥:
composer config -g cache-files-maxsize "1G",比频繁 GC 更省时间 - 清理过期项用
composer clear-cache --gc,别总用clear-cache全删——那相当于放弃所有缓存收益 - 注意:TTL 只控制文件缓存,不影响
repo/下的元数据缓存;后者靠cache-repo-ttl控制(默认 15 天),但很少需要动
真正让缓存“活起来”的关键,往往不在参数本身,而在路径、权限、协议、key 四者严丝合缝——少一个,缓存就只是磁盘上一堆没人读的 zip 文件。


















