composer archive不能当离线部署包用,因其仅为源码归档工具,不包含vendor/、不读composer.lock、不处理autoload,解压后缺少vendor/autoload.php必然报class not found。

直接用 composer archive 打包项目,无法实现离线分发——它不包含 vendor/、不读 composer.lock、也不处理 autoload,解压后连 vendor/autoload.php 都不存在,必然报 Class not found。
为什么 composer archive 不能当离线部署包用
它本质是源码归档工具,只按 composer.json 的 autoload 和 extra.archive-includes 复制文件,完全不碰依赖安装逻辑。默认排除 vendor/、node_modules/、.git/,哪怕你刚跑完 composer install,archive 输出里依然没有一个第三方类。
- 打包结果不含
vendor/autoload.php,require 就失败 -
composer.lock不会被自动加入,离线机上composer install会重新解析依赖,版本可能漂移 - 私有包若走 git source 模式(而非 dist),archive 后的包在离线环境根本找不到源
- 文件名由
composer.json的name和version决定,没写version时 fallback 到dev-main或 commit hash,不可控
离线分发必须先装再打,不是先打再装
真正能落地的流程是:在与目标环境一致的联网机器上,先完整执行 composer install,再用系统命令(zip 或 tar)归档整个项目目录。这不是 archive 命令该干的事,但它是唯一稳定路径。
- 运行
composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction,确保vendor/干净、autoload 高效、无交互阻塞 - 检查
vendor/composer/installed.json是否存在——它是 autoload 映射依据,缺失会导致类加载失败 - 手动归档:
zip -r app-release.zip . -x "node_modules/*" ".git/*" "tests/*",显式剔除非运行必需内容 - 务必包含
composer.json和composer.lock,后者是版本锁定的唯一凭证
私有包离线可用的关键:强制 dist + 预下载 + 路径校验
私有 Git 仓库默认走 source(clone),离线即死。必须提前切换为 dist 模式,并把 tarball 下载到本地缓存,否则 vendor/ 里存的是空壳或软链。
- 构建前设全局镜像:
composer config -g repo.packagist composer https://packages.internal/,确保所有包走内网源 - 删掉旧
vendor/,再跑composer install --no-dev --prefer-dist,验证vendor/composer/installed.json中每个包的dist.url是否指向内网地址 - 若用
type: "path"本地开发,离线前必须转成type: "artifact",并配置绝对路径:{"type":"artifact","url":"/data/archives/"} - 检查压缩包内私有包是否真实解压——不要只看目录是否存在,要确认
src/下有类文件、composer.json可读
离线机上安装时必须切断网络通路
光靠 --no-network 参数不够,Composer 在 install 阶段仍会尝试访问 packagist.org 校验元数据。必须用环境变量硬隔离,且跳过所有可能触发网络的环节。
- 执行前设
COMPOSER_DISABLE_NETWORK=1,这是强制开关,其他参数都拦不住初始校验 - 运行
composer install --no-plugins --no-scripts --no-autoloader,避免插件和脚本触发远程调用 - 补一记
composer dump-autoload -o,确保类映射生效——别指望 vendor 里自带的 autoload 文件在新环境一定可用 - 如果目标机 PHP 版本低,构建时加
--ignore-platform-reqs,否则install会因扩展缺失直接退出
最易被忽略的一点:离线部署不是“打包完就结束”,而是“打包+验证+隔离”三步闭环。少验证一次 dist.url,少设一个 COMPOSER_DISABLE_NETWORK=1,上线就卡在 Could not find package。真正的稳定性来自对每层依赖来源的显式控制,而不是依赖 Composer 默认行为。











