--no-dev 不生效的主因是 autoload 配置错误导致测试类被主 autoloader 加载,而非仅依赖安装问题;需检查 composer.json 的 autoload(非 autoload-dev)是否误含 Tests 命名空间,并配合 --optimize-autoloader 和 lock 文件状态综合排查。

为什么 --no-dev 有时不生效?
它只跳过 require-dev 区块里的包,但如果你的 autoload-dev 或测试类被主代码意外引用(比如 tests/ 目录被 autoload 扫进去了),Composer 仍会尝试加载它们——哪怕没安装。常见于 Laravel、Symfony 项目里误配了 autoload 的 psr-4 映射,把 Tests\ 也映射进生产 autoloader。
- 检查
composer.json的autoload(不是autoload-dev)是否包含测试命名空间或路径 - 运行
composer dump-autoload --no-dev后,用composer show --dev确认 dev 包确实没列出来 - 如果用了
config.platform模拟低版本 PHP,某些 dev 包可能因平台约束被“降级保留”,得配合--ignore-platform-req=ext-*清理
composer install --no-dev 和 composer update --no-dev 的区别
前者按 composer.lock 精确还原依赖,跳过所有 require-dev;后者会重新解析依赖树,但依然忽略 require-dev —— 这意味着:如果 lock 文件里记录了 dev 包,install --no-dev 能彻底跳过;而 update --no-dev 可能因依赖传递引入新 dev 包(比如某个非 dev 包在它的 require-dev 里声明了工具,但该工具又被其 require 间接拉进来)。
- 部署必须用
composer install --no-dev,不是update -
composer update --no-dev仅适合开发环境清理后重生成 lock,且要确认composer.lock的packages-dev字段为空 - CI/CD 中建议加
--dry-run先验证:composer install --no-dev --dry-run
CI/CD 部署时漏掉 --no-dev 的典型后果
最直接的表现是:PHP 单元测试框架(如 phpunit/phpunit)或代码分析工具(如 phpstan/phpstan)被装进生产环境,不仅浪费磁盘和内存,更严重的是——这些包的 autoloader 可能污染生产类加载顺序,导致 Class not found 错误(尤其当它们注册了同名 classmap 或 files 加载器)。
- 错误现象:
PHP Fatal error: Class 'PHPUnitFrameworkTestCase' not found出现在生产日志里,说明某处代码 runtime 引用了测试类 - 用
composer show --installed快速排查是否混入了phpunit、mockery、doctrine/orm(带-dev后缀的变体)等 - Docker 构建中记得在
RUN composer install后加&& composer dump-autoload --optimize --no-dev,避免 autoload 生成冗余映射
配合 config.optimize-autoloader 才算真正优化
--no-dev 只控制装不装包,不控制 autoloader 性能。如果没开优化,Composer 仍会为每个 PSR-4 命名空间扫描整个目录,包括那些本该被 --no-dev 排除的测试文件夹。
- 部署前确保
composer.json有:"config": { "optimize-autoloader": true, "apcu-autoloader": true } - 或者运行时加参数:
composer install --no-dev --optimize-autoloader --apcu-autoloader - 注意:
--apcu-autoloader要求 APCu 扩展已启用,否则会静默失败,可用php -m | grep apcu验证
--no-dev,而在它和 autoloader 配置、lock 文件状态、甚至扩展可用性之间的耦合。










