必须强制走dist并清理旧缓存:联网机执行composer install --no-dev --prefer-dist --no-progress填充~/.composer/cache/files/,离线机先composer clear-cache再解压缓存,最后composer install --no-interaction读取。

提前缓存所有包到 ~/.composer/cache/files/
Composer 的缓存机制只在 install 或 update 时自动填充,但默认行为不保证“下全所有 ZIP”——尤其当 composer.json 里有 "require-dev" 或某些包走 source(git clone)而非 dist(zip)时,缓存目录会缺文件。
真正能用于离线的缓存,必须强制走 dist 并确保无遗漏:
- 在联网机器上执行:
composer install --no-dev --prefer-dist --no-progress(--no-dev避免 dev 包漏缓存;--prefer-dist强制用 zip,跳过 git 拉取) - 确认缓存已满:检查
~/.composer/cache/files/下是否有对应vendor/name/version-hash/目录,且里面是.zip文件(不是空目录或.git) - Windows 用户注意路径:
C:\Users\用户名\AppData\Roaming\Composer\Cache\files\,不能只拷子目录,必须整包打包 - 别信
composer update --dry-run:它不触发下载,也不会写缓存
打包缓存后怎么让离线机真正读到
离线机上光解压缓存目录还不够——Composer 默认仍会尝试联网校验元数据,除非你让它“相信缓存可信”。关键动作是清空旧缓存 + 强制复用:
- 先运行:
composer clear-cache(避免残留旧哈希干扰) - 再解压缓存包到原路径:
tar -xzf deps.tgz -C ~(Linux/macOS)或手动覆盖 Windows 路径 - 最后执行:
composer install --no-interaction(不加--no-cache!否则它又绕过缓存) - 如果报
Package not found,大概率是某包在composer.lock里指定了"source"类型(如"url": "git@..."),这种包根本不会进files/缓存,得提前改 lock 文件或换镜像源
为什么只拷 vendor/ 不够,非得动缓存
直接复制 vendor/ 是最省事的离线方案,但它和缓存是两套逻辑:
-
vendor/复制后需配COMPOSER_DISABLE_NETWORK=1 composer install --no-plugins --no-scripts --no-autoloader,否则仍会联网校验 -
~/.composer/cache/files/方案的优势在于:可复用同一份缓存给多个项目,且不依赖特定composer.lock版本(只要包版本在缓存中存在) - 坑点:缓存 ZIP 文件名含 SHA256 哈希,不能重命名;若你手动改过
composer.json约束(比如把"^2.0"改成"^2.1"),即使缓存里有 2.1.x 的 ZIP,Composer 也可能因哈希不匹配拒绝使用 - 验证是否真读缓存:加
-v参数运行composer install,看到Downloading ... (cached)才算成功
缓存方案失效的典型信号
你以为缓存齐了,结果离线机一跑就报错?常见原因很具体:
-
Could not fetch https://repo.packagist.org/packages.json→ 没设COMPOSER_DISABLE_NETWORK=1,或设了但没生效(比如用export写进 shell profile 但没 source) -
Failed to decode response: zlib_decode(): data error→ 缓存 ZIP 文件损坏,删掉对应vendor/name/hash/目录重试 -
Package vendor/name is not available in a version installable using your PHP version→composer.lock里该包的php版本约束和离线机实际 PHP 版本不匹配(比如锁的是"php": "^8.2",但离线机是 8.1.10) - 某些包(如
symfony/flex)带插件,即使缓存齐全,composer install仍会触发post-install-cmd联网 → 必须加--no-plugins --no-scripts
缓存不是“放进去就能用”,它是 Composer 安装链里最脆弱的一环:依赖哈希、路径、PHP 版本、扩展、lock 文件结构全部对齐,少一个都可能静默失败。











