如何在CI/CD流水线中通过缓存优化Composer安装速度?

15次阅读

CI中composer install慢的根源是每次重建vendor目录且无有效缓存;提速关键在于基于composer.lock哈希精准缓存vendor目录,并配合–no-interaction、–prefer-dist、–optimize-autoloader等参数。

如何在CI/CD流水线中通过缓存优化Composer安装速度?

Composer install 为什么在CI中特别慢?

因为默认每次都会重新下载所有依赖包,尤其是 vendor/ 目录完全重建,且没有复用已有的 php 扩展缓存或 Composer 自身的 global cache。CI 环境通常不保留上一次构建的文件,导致重复拉取相同版本的包(比如 monolog/monolog v2.13.0),网络+解压+安装三重开销叠加。

用 –no-interaction 和 –prefer-dist 是基础但不够

这两个参数能跳过交互提示、强制走压缩包而非 git 克隆,属于必须项,但无法解决“每次重下”的本质问题。真正提速靠的是缓存策略组合:

  • --no-interaction --prefer-dist --optimize-autoloader --classmap-authoritative:减少运行时 autoload 开销,适合生产环境 CI
  • 必须配合 composer install 前的缓存 restore 步骤,否则参数再优也白搭
  • 注意 composer.lock 文件必须提交到仓库,否则缓存失效或版本漂移

github Actions 中缓存 vendor 目录最稳的方式

直接缓存 vendor/ 目录比缓存 Composer 的 global cache 更可靠——因为后者受 PHP 版本、扩展、composer.json 配置(如 platform)影响大,容易误命中;而 vendor/ 缓存只依赖 composer.lock 的 hash,精准度高。

steps:   - uses: actions/checkout@v4   - name: Cache vendor directory     uses: actions/cache@v4     with:       path: vendor       key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}   - name: Install dependencies     run: composer install --no-interaction --prefer-dist --optimize-autoloader --classmap-authoritative

关键点:key 必须包含 hashFiles('**/composer.lock'),不能只用 PHP 版本或 OS;否则 lock 文件一变,旧缓存仍被复用,导致依赖不一致。

gitlab CI 里用 cache: key + policy 要避开路径陷阱

GitLab 不支持像 GitHub 那样自动 hash 文件内容,得手动用 script 计算 lock 文件 hash,并确保 cache: 块中的 key:paths: 严格匹配:

before_script:   - export COMPOSER_CACHE_DIR="$CI_PROJECT_DIR/.composer-cache"   - mkdir -p $COMPOSER_CACHE_DIR 

cache: key: ${CI_COMMIT_REF_SLUG}-composer-${CI_JOB_NAME}-${CI_PIPELINE_ID} paths:

  • vendor/
  • .composer-cache/

stages:

  • build

build-job: stage: build script:

  • | if [ -f composer.lock ]; then LOCK_HASH=$(sha256sum composer.lock | cut -d' ' -f1) echo "Using composer.lock hash: $LOCK_HASH"

    实际缓存 key 应该基于这个 hash,但 GitLab 不支持动态 key,所以建议用 include+template 或外部工具生成

    fi

  • composer install --no-interaction --prefer-dist --optimize-autoloader

真实项目中更推荐把 vendor/ 放进 cache: paths: 并用固定 key(如 composer-${CI_COMMIT_REF_SLUG}),同时在 script 开头加校验逻辑:如果 vendor/autoload.php 存在但 composer install 报错 “package not found”,说明缓存脏了,需加 rm -rf vendor 清理后重装。

缓存不是开了就快,关键是让缓存 key 精确反映依赖状态;composer.lock 变了,缓存就必须失效——这点最容易被忽略,也是 CI 中出现“本地好使、CI 报错”的常见根源。

text=ZqhQzanResources