不会自动排除,需显式使用 --no-dev 参数安装;否则生产环境会混入开发包,增大体积并引入安全风险。

require-dev 里的包在生产环境会被自动排除吗
不会自动排除,但默认不安装——关键看 composer install 是否加了 --no-dev 参数。Composer 默认行为是:本地运行 composer install 时会装 require 和 require-dev;而部署到生产环境时,必须显式加上 --no-dev 才跳过 require-dev 下的包。
容易踩的坑:
- CI/CD 脚本漏写
--no-dev,导致生产镜像里混入phpunit、larastan等开发工具,增大体积且引入安全风险 -
composer update不受--no-dev影响,它始终读取完整composer.json,所以更新后务必重新跑带--no-dev的 install - 某些私有包若同时出现在
require和require-dev中,版本冲突会导致安装失败,需手动清理重复声明
require-dev 包能否被生产代码直接使用
技术上可以,但属于设计错误。Composer 不限制运行时调用,但 require-dev 包不保证在生产环境存在,一旦漏掉 --no-dev 或误删 vendor/autoload.php 的加载逻辑,就会触发 Class not found 错误。
典型问题场景:
- 把
symfony/var-dumper写在require-dev,却在控制器里调用dump()—— 本地正常,上线 500 - 测试用的 Mock 工具(如
mockery/mockery)被误用于服务类的构造函数中,导致容器构建失败 -
autoload-dev配置的测试类路径被主应用入口文件引用,上线后找不到对应 PSR-4 命名空间
如何验证当前 vendor 中是否包含 require-dev 包
最可靠的方式是检查 composer.lock 文件中的 packages-dev 字段是否存在,以及对比 vendor/ 目录实际内容与 composer show --dev 输出。
实操建议:
- 运行
composer show --dev查看当前已安装的 dev 包列表(仅当vendor/里真有这些包时才显示) - 执行
composer install --dry-run --no-dev,观察输出中是否还有 dev 包被标记为“would be installed” - 部署前加一道检查脚本:
if [ -n "$(ls vendor/phpunit* 2>/dev/null)" ]; then echo "ERROR: dev packages detected"; exit 1; fi
require-dev 中的自动加载(autoload-dev)影响范围
autoload-dev 只控制 Composer 生成的 vendor/autoload.php 是否包含对应 PSR-4/PSR-0/classmap 映射,不影响包本身的安装与否。也就是说,即使某个包只在 require-dev 中,只要它的 autoload-dev 被加载,其测试类就能被 require 到——前提是该 autoloader 被引入了。
需要注意:
-
autoload-dev不会自动合并进主autoload,必须通过require 'vendor/autoload.php'才生效;单独 require 某个测试文件时,不会触发autoload-dev - Laravel 的
phpunit.xml通常显式设置bootstrap="vendor/autoload.php",所以测试能跑通;但 Web 请求走的是public/index.php,它只加载主 autoloader,不加载 dev 部分 - 如果想让某些工具类在开发和生产都可用,应移入
require并改用autoload,而非依赖autoload-dev
真正容易被忽略的是:Composer 的 require-dev 不是“作用域隔离”,而是“安装策略开关”。它不改变代码可见性,也不参与运行时权限控制——一切取决于你有没有在生产环境执行那条带 --no-dev 的命令,以及你的代码有没有偷偷依赖了不该依赖的东西。










