composer install --no-dev 是生产环境精简 vendor 的标准做法,仅安装 require 列表依赖、跳过 require-dev 包,需基于现有 composer.lock 执行,配合 --optimize-autoloader --classmap-authoritative 可提升性能且保障可重现性。

composer install --no-dev 是生产环境精简 vendor 的标准做法
直接运行 composer install --no-dev 就能跳过 require-dev 中声明的包(如 phpunit/phpunit、friendsofphp/php-cs-fixer),只安装 require 列表里的依赖。这是最稳妥、最被广泛验证的方式,比 composer update --no-dev 更适合部署。
- 必须在已存在
composer.lock的项目中执行,否则会报错“no lock file found” - 如果本地开发时没提交最新的
composer.lock,线上执行会按旧 lock 文件安装,可能遗漏新依赖 -
--no-dev不影响自动加载逻辑,autoload-dev部分只是不被安装,不会导致class not found
为什么不能只靠 composer dump-autoload --optimize?
composer dump-autoload --optimize 只是优化自动加载器(生成 vendor/composer/autoload_classmap.php),它不删任何包,vendor 体积完全不变。有人误以为“优化 = 精简”,结果上线后仍带着几十 MB 的测试工具。
- 该命令只影响
vendor/composer/autoload_*.php文件,和包体积无关 - 在 CI/CD 流水线里,应先
install --no-dev,再dump-autoload --optimize --classmap-authoritative -
--classmap-authoritative能让 autoloader 完全忽略文件系统扫描,提升性能,但前提是确认所有类都已在 classmap 中(即无动态 require)
CI/CD 中常见错误:用 composer update --no-dev 替代 install
很多脚本写成 composer update --no-dev,这会导致线上环境重新解析依赖并生成新 composer.lock,破坏可重现性。生产部署必须基于锁定的版本,而非实时解析。
-
update会修改composer.lock,而生产机器通常不应有写权限或 Git 提交能力 - 若 lock 文件中某包指定了
"dev-master",update --no-dev仍会拉取最新 commit,但install --no-dev严格按 lock 固定版本 - 推荐部署流程:
rm -rf vendor composer.lock git checkout -- composer.lock composer install --no-dev --no-interaction --optimize-autoloader
额外瘦身:清理未使用的 bin 脚本和文档
--no-dev 不会删除 vendor/bin 下残留的二进制文件(比如之前装过 phpunit,后来移除了但 bin/phpunit 还在)。这些文件虽小,但可能暴露调试入口。
- 可用
composer install --no-dev --no-scripts阻止 post-install-cmd 执行(避免某些包自动生成 demo 或缓存) - 部署后手动清理:
find vendor/bin -type f ! -name 'phpstan' ! -name 'psalm' ! -name 'phpcs' -delete 2>/dev/null
(按需保留静态分析工具) - 注意:某些正式包(如
laravel/installer)也会放 bin,删前确认是否业务必需
实际部署时最容易被忽略的是 lock 文件的时效性与权限控制——哪怕命令全对,如果 composer.lock 没随代码一起更新,--no-dev 也救不了体积失控的 vendor。










