必须缓存~/.composer/cache而非vendor/,因其仅依赖composer.lock哈希且与php版本、扩展等环境无关;vendor/缓存易致autoload不兼容而报错;ci中需用lock文件哈希+php版+composer版构建缓存key,并配--prefer-dist等参数确保生效。

缓存路径必须是 ~/.composer/cache,不是 vendor/
缓存 vendor/ 看似快,实则高风险:不同 PHP 版本、ext-apcu 开关状态、甚至文件系统大小写敏感性,都会让生成的 autoload_static.php 或 classmap.php 不兼容。CI 一次缓存混用,下次就报 Cannot declare class 或 include(): Failed opening。
真正该缓存的是 Composer 自己的包缓存目录——它只跟 composer.lock 哈希绑定,与运行环境无关。所有主流 CI 平台(GitHub Actions、GitLab CI、CircleCI)都推荐且安全缓存 ~/.composer/cache。
-
~/.composer/cache是默认路径;若自定义过COMPOSER_CACHE_DIR,缓存路径要同步改 - GitLab CI 中写
cache: { paths: [~/.composer/cache] },别加vendor/ - GitHub Actions 用
actions/cache@v4,path字段填~/.composer/cache
缓存 key 必须包含 composer.lock 哈希,不能只靠分支名
只用 $CI_COMMIT_REF_SLUG 或 main 这类静态 key,会导致 lock 文件变更后仍命中旧缓存,结果是“看似安装成功,实际依赖没更新”。
正确做法是让 key 绑定 composer.lock 内容本身。GitLab CI 示例:
cache:
key: "$CI_COMMIT_REF_SLUG-$(sha256sum composer.lock | cut -d' ' -f1)"
paths:
- ~/.composer/cache
GitHub Actions 更推荐:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
- 哈希值变了 → 缓存 miss → 触发全新
composer install - 哈希值没变 → 缓存 hit → 复用已下载的 dist 包,跳过网络拉取
- 如果项目还用了
platform.php或config.platform,建议把该配置内容也纳入 key 计算(否则可能因平台约束不一致导致安装失败)
composer install 必须带 --prefer-dist --no-progress --no-scripts
这些参数不是可有可无的优化项,而是缓存生效的前提条件:
-
--prefer-dist:强制走压缩包安装,避免 git clone —— 只有 dist 包才被~/.composer/cache管理;源码模式不进缓存 -
--no-progress:关闭进度条输出,减少日志体积,部分 CI 平台对长输出有截断或超时风险 -
--no-scripts:防止post-install-cmd类脚本在 CI 中误触发(比如本地开发用的生成 swagger 文档),除非你明确需要且已验证其幂等性 - 别漏
--no-dev:CI 构建通常不需要phpunit、phpstan,它们不进 classmap,却可能污染 autoloader 行为
CI 脚本开头要设 COMPOSER_MEMORY_LIMIT
很多 CI 镜像中 PHP CLI 的 memory_limit 默认是 128M 或 256M,而 Composer 解析大型依赖树(如 Laravel + dozens of packages)很容易爆内存,表现是 composer install 卡住、无错误退出、或报 Killed —— 这不是网络问题,是 OOM 被系统 kill。
解决方式统一前置设置:
-
export COMPOSER_MEMORY_LIMIT=-1(推荐,禁用限制) - 或
export COMPOSER_MEMORY_LIMIT=2G(显式指定,更可控) - 不要写
php -d memory_limit=-1 composer install:部分 CI 镜像里这个参数对 Composer 子进程不生效 - Docker 构建中,检查基础镜像是否硬编码了
memory_limit(php -i | grep memory_limit)
缓存和参数只是加速手段,真正的底线是:composer.lock 必须提交,composer install 必须在它存在时运行,且不能被任何环节悄悄替换成 update —— 否则所谓“缓存”只是给不可重现的构建加速而已。










