正确做法是先运行 composer install –no-dev –optimize-autoloader 清理开发依赖并优化自动加载,再用 composer archive 命令按配置排除非必要文件打包,同时确保 classmap 完整、保留最小必要 composer.json 字段。

composer install –no-dev 之后再 zip,但别直接压缩 vendor 目录
直接 zip -r project.zip . 会把 vendor/ 里所有开发依赖(比如 phpunit/phpunit、symfony/var-dumper)也打进去,体积大、有安全风险、还可能混入调试工具。正确做法是先清理无用文件,再精确打包。
- 运行
composer install --no-dev --optimize-autoloader,确保vendor/只含运行时依赖,且 autoloader 已优化 - 删掉
vendor/bin/(除非你明确需要 CLI 工具)、vendor/*/tests、vendor/*/Tests、vendor/*/README.md等非运行必需内容 - 排除
node_modules/、.git/、.env、composer.lock(分发时通常不带 lock 文件,接收方应自行 install)
用 composer archive 命令更可控
composer archive 是 Composer 内置的打包命令,比手动 zip 更可靠,能自动跳过 excluded files(如 .gitignore 和 composer.json 中定义的 archive.ignore)。
- 在
composer.json里加配置:"archive": { "exclude": [".git", ".env", "tests/", "Tests/", "phpunit.xml", "phpstan.neon"] } - 执行
composer archive --format=zip --dir=dist/ myapp,会生成dist/myapp-1.2.3.zip(版本号取自composer.json的version字段) - 注意:该命令默认不执行
install,所以必须提前确保vendor/已就绪(或搭配--no-dev参数使用脚本封装)
打包前必须检查 autoload 的 classmap 是否完整
如果项目用了 "classmap": ["src/"] 或动态加载逻辑,而打包时没重新生成 classmap,运行时就会报 Class not found —— 这个错误常被误判为路径问题,实际是 autoloader 缺失映射。
- 打包前务必运行
composer dump-autoload --optimize --classmap-authoritative - 确认
vendor/composer/autoload_classmap.php文件存在且非空 - 若项目含 PSR-4 自动加载,也要检查
autoload_psr4.php是否包含全部命名空间映射
分发包里要不要放 composer.json?
要放,但只放最小必要字段。接收方不需要重装依赖,但需要知道最低 PHP 版本、扩展要求、以及是否需额外配置。
- 保留
name、description、type、require、require-dev(可清空)、autoload、config.platform(用于锁定 PHP 和扩展版本) - 删掉
scripts、repositories、extra(除非你明确依赖其中某项) - 特别注意:
config.platform.php必须设为真实目标环境版本,否则composer install在低版本 PHP 上可能失败
实际打包动作往往卡在“以为 vendor 就是全部”,其实真正影响运行的是 autoloader 映射 + 平台约束 + 排除逻辑。漏掉其中一环,ZIP 包在另一台机器上大概率启动失败,而且错误提示根本不会指向打包环节。