生产环境部署必须使用 composer install --no-dev,否则会安装 require-dev 依赖造成资源浪费和安全风险;需配合 --optimize-autoloader 和 --classmap-authoritative,并验证 vendor 中无 phpunit 等 dev 包。

生产环境部署时跳过 require-dev 依赖
默认情况下 composer install 会安装 require 和 require-dev 下的所有包,这在生产环境不仅浪费资源,还可能引入安全风险或冲突。关键不是“删掉 dev 依赖”,而是让 Composer 明确知道“现在不需要它们”。
- 上线部署务必使用
composer install --no-dev,这是最直接、最可靠的方式 - 如果项目已运行过
composer install(含 dev 包),再执行--no-dev不会自动卸载已有 dev 包——必须先删掉vendor/或用composer update --no-dev -
composer install读取的是composer.lock,只要 lock 文件里记录了 dev 包,不加--no-dev就仍会装;而composer update --no-dev会更新 lock 文件,剔除 dev 包的记录
CI/CD 流水线中确保 --no-dev 生效
很多线上部署失败,是因为 CI 脚本用了 composer install 却没加 --no-dev,或者误用了 composer require(它默认写入 require,但加 -d 会写入 require-dev,且不带 --no-dev 的 install 仍会装)。
- 流水线脚本中固定写死:
composer install --no-dev --optimize-autoloader --classmap-authoritative - 避免在生产环境运行
composer update—— 它会重写composer.lock,可能意外拉入新 dev 包 - 检查
COMPOSER_NO_DEV环境变量:设为1可全局禁用 dev 包(但不如显式加--no-dev直观,容易被忽略)
如何验证生产环境真没装 dev 依赖
光靠命令不够,得看结果。常见误判是看到 vendor/autoload.php 还在,就以为一切正常——其实 autoload 本身不暴露是否加载了 dev 包。
- 检查
vendor/目录下是否存在明显属于 dev 的包,比如phpunit/phpunit、mockery/mockery、symfony/var-dumper(非框架主包时) - 运行
composer show --dev—— 如果提示 “No dependencies in require-dev” 或直接报错 “Command 'show' is not defined”,说明 dev 包确实未安装 - 注意:有些包同时出现在
require和require-dev(如psr/log),这时它仍会被装,属正常行为
composer show --dev # 输出为空或提示无 dev 依赖,才表示 clean
require-dev 里的工具类包要小心 runtime 依赖
像 phpstan/phpstan、infection/infection 这类静态分析工具,通常只在 CI 中调用,但如果代码里写了 class_exists('PHPStan\...') 或通过 class_alias 动态引用,运行时就会抛出 Class not found 错误——哪怕你加了 --no-dev。
- 所有对 dev 包的运行时调用,必须包裹
class_exists()或interface_exists()判断 - 不要在生产代码的
use语句中直接引用 dev 包的类(PHP 会在解析阶段报错) - 如果某包既提供 CLI 工具又提供运行时功能(如
symfony/console),确认它是否真的只用于开发:若是框架核心组件,应移入require
真正容易被忽略的点是:--no-dev 只控制安装,不改变代码逻辑。一旦运行时代码依赖了未安装的类,PHP 解析器会在第一时间崩溃,不会等你到请求处理阶段。










