composer中require和require-dev的区别_composer开发环境依赖详解【对比】

7次阅读

require 和 require-dev 的划分标准是类是否在运行时被业务代码调用:若会则必须进 require,否则如仅用于测试、CI 或静态分析则属 require-dev;误将 dev 工具混入运行时路径会导致 –no-dev 部署时报错。

composer中require和require-dev的区别_composer开发环境依赖详解【对比】

require 和 require-dev 不是“开发用”和“生产用”的简单划分

关键判断标准只有一个:这个包的类是否会在运行时被业务代码 new、use 或调用? 如果会,就必须进 require;如果只在 phpunit 命令里跑、只在 CI 脚本里执行、或只在本地 phpstan 扫描时加载,那就属于 require-dev

常见误判:以为“我在本地写测试才用 PHPUnit”,所以它“只是开发用”——这没错;但更深层风险是:一旦你在某个控制器里写了 new PHPUnitFrameworkTestCase()(哪怕只是临时调试),上线后执行 composer install --no-dev 就直接报 class not found。这不是 Composer 的 bug,是你把 dev 工具混进了运行时路径。

composer require 和 composer require –dev 的行为差异

两个命令表面只差一个 --dev,但写入位置和后续影响完全不同:

  • composer require phpunit/phpunit → 写入 composer.jsonrequire 字段 → 每次 composer install 都装,线上也装
  • composer require --dev phpunit/phpunit → 写入 require-dev 字段 → 本地默认装,但 composer install --no-dev 完全跳过

注意:composer require-dev 是无效命令(Composer 不识别该子命令),必须写成 composer require --dev。漏掉空格或写错连字符,就会误装进 require

autoload-dev 不是给 require-dev 包自己用的

autoload-dev 是个常被误解的配置项。它不是让 phpunit/phpunit 自己能自动加载,而是告诉 Composer:“当本项目启用了 dev 模式(即装了 require-dev 包)时,请额外把测试目录也加进自动加载规则”。

典型用法:

{     "autoload": {         "psr-4": { "app\": "src/" }     },     "autoload-dev": {         "psr-4": { "Tests\": "tests/" }     } }

这意味着:只有你本地执行了 composer install(没加 --no-dev),Tests\ 命名空间才会被注册进 vendor/autoload.php;线上用 --no-dev,这个映射压根不会生效 —— 即便 tests/ 目录还在,也不会被自动加载。

部署时 –no-dev 不是“可选优化”,而是必须动作

生产环境执行 composer install --no-dev 不只是为了省几 MB 磁盘空间。更重要的是:

  • 避免非预期类加载:比如 friendsofphp/php-cs-fixer 会注册大量 symfony 组件,它们可能覆盖或干扰你的运行时依赖版本
  • 减少攻击面:psy/psyshsymfony/var-dumper 这类调试工具若留在线上,可能被利用为交互式执行入口
  • 防止 CI/CD 流水线污染:某些工具(如 phpstan/phpstan)依赖特定 PHP 扩展或扩展版本,线上环境未必满足,导致部署失败

真正容易被忽略的一点:CI 环境通常要跑测试,所以得装 require-dev;但很多团队把 CI 构建产物直接当部署包推到线上,结果把 phpunit 一起带过去了——这相当于把 ide 插件打包进发布版本。

text=ZqhQzanResources