离线部署失败主因是仅传composer.lock就执行install,因lock文件不含代码且仍会联网校验;真正可行方案是完整打包vendor目录,并用COMPOSER_DISABLE_NETWORK=1配合--no-plugins等参数跳过网络阶段,最后dump-autoload确保类加载正确。

离线部署失败,八成是因为只传了 composer.lock 就跑 composer install——它根本不会从本地还原 vendor,而是坚持联网查包元数据,哪怕 vendor 目录明明就在旁边。
为什么只拷 composer.lock 和 composer.json 一定失败
因为 composer.lock 只存哈希、版本和 dist URL(比如 "url": "https://api.github.com/repos/monolog/monolog/zipball/..."),不带任何代码。Composer 离线时仍会尝试请求这个 URL,或去 repo.packagist.org 拉 packages.json,结果就是 Could not fetch 或 Connection refused。
-
vendor/是“离线依赖”的本体,不是产物,是前提 - 删掉
vendor/再跑composer install,等同于要求 Composer 凭空造包 - 有人试过用
composer archive打 zip,但它只打项目源码,不包含vendor/,解压后require 'vendor/autoload.php'必然报错
真正能落地的离线包,必须含完整 vendor/ 目录
核心动作不是“让 Composer 离线”,而是“绕过它的网络阶段”。前提是:开发机和目标机 PHP 版本、扩展(如 ext-openssl)、架构(x86_64 vs aarch64)一致。
- 开发机执行:
composer install --no-dev --prefer-dist --optimize-autoloader,确保vendor/干净、无 dev 文件、autoload 高效 - 打包前删掉:
vendor/bin/(Windows 软链失效)、vendor/composer/installed.json(含绝对路径,易导致 autoload 异常) - 用命令行压缩:
zip -r app-offline.zip . -x "node_modules/*" ".git/*",别用图形化工具(可能改权限或加元数据) - 验证方式:在目标机解压后,写个
test.php:require 'vendor/autoload.php'; echo "OK";,能执行不报错才算过关
内网服务器上还原 vendor,不能直接跑 composer install
很多人解压完就立刻 composer install,结果还是连网失败——因为默认行为仍会校验远程元数据,哪怕 vendor/ 已存在。
- 先设环境变量彻底断网:
COMPOSER_DISABLE_NETWORK=1(Linux/macOS)或set COMPOSER_DISABLE_NETWORK=1(Windows) - 运行:
composer install --no-plugins --no-scripts --no-autoloader,跳过所有插件、脚本和 autoload 重建 - 最后强制刷新加载器:
composer dump-autoload -o,确保类路径与当前目录匹配 - 如果目标机 PHP 缺扩展(如
ext-gd),加--ignore-platform-reqs绕过检查(注意:这只是安装跳过,运行时报错照旧)
最容易被忽略的静默故障点
不是报错,而是“看起来成功了,运行时报 Class not found”。这类问题往往源于:
-
composer.lock里有"minimum-stability": "dev",记录了dev-master这类无法离线解析的版本 - 私有包用了 GitLab 地址,但目标机没配 SSH key 或无法访问该地址(这不是纯离线)
-
vendor/composer/autoload_psr4.php里路径写死为开发机绝对路径(极少,但某些自定义 autoloader 会) - PHP 版本小版本不一致(如开发机 8.1.22,目标机 8.1.10),导致某些包的
platform约束被跳过


















