Composer.json中require-dev区别_Composer开发依赖配置指南【规范】

1次阅读

require 中的包是项目运行时必需的,删掉会导致 http 请求或业务逻辑失败;require-dev 中的包仅用于开发、测试、构建等阶段,上线后不参与运行,执行 composer install –no-dev 时会被跳过。

Composer.json中require-dev区别_Composer开发依赖配置指南【规范】

require-dev 和 require 的根本区别在哪

区别不在“要不要装”,而在“什么时候装、给谁用”。require 里的包是项目运行时必需的,比如 monolog/monolog 用于日志;require-dev 里的包只在开发阶段需要,比如 phpunit/phpunitfriendsofphp/php-cs-fixer,上线后完全不参与运行。

关键判断标准:删掉这个包,项目还能不能正常响应 HTTP 请求、处理业务逻辑?能——就该放 require-dev;不能——必须进 require

  • 执行 composer install --no-dev 时,require-dev 内容会被跳过,生成的 vendor/ 更轻量
  • composer update 默认同时更新 requirerequire-dev,但 CI 流水线常加 --no-dev 防止测试工具污染生产环境
  • 如果把 phpunit 放进 require,部署时会多下几十 MB 无用代码,还可能引入非预期的 autoloader 冲突

哪些工具必须塞进 require-dev

不是“开发者用的”就自动归类,而是看它是否参与构建、测试、检查流程,且不暴露给运行时代码。常见误放点:把 doctrine/orm 的命令行工具当成 dev 工具,其实它是运行时 ORM 的一部分,必须放 require

  • phpunit/phpunitpestphp/pest:纯测试执行器,不被业务代码 use,只在 ./vendor/bin/phpunit 调用
  • phpstan/phpstanpsalm/phar:静态分析工具,仅本地或 CI 中执行,不 autoload 到应用中
  • symfony/var-dumper:虽然常被 dump() 调用,但它本身是调试辅助,线上应禁用;若项目依赖其 Cloner 类做序列化,就得挪到 require
  • laravel/pintphp-cs-fixer:代码格式化工具,只在 pre-commit 或 CI 中触发,和运行时零耦合

require-dev 里混进 runtime 依赖的典型错误现象

最常踩的坑:某个包在 require-dev 里,但你的 src/ 文件直接 use 它的类,甚至调用它的方法——上线跑 composer install --no-dev 后,直接 class not found

错误示例:require-dev 里有 fakerphp/faker,但你在 Entity 构造函数里写了 new FakerGenerator()。这等于把假数据生成逻辑写进了业务模型,违反了依赖边界。

  • 现象:本地 php artisan test 正常,但部署后访问首页报 Class 'FakerGenerator' not found
  • 查法:用 composer show --dev 确认包是否真在 require-dev;再 grep 全局搜索该类名是否出现在 src/app/
  • 修复:要么把包移到 require(仅当它确属运行时依赖),要么重构代码——把 fake 数据逻辑抽到测试专用 factory 类里,业务代码不碰它
  • 注意:autoload-dev 字段只影响自动加载路径,不改变依赖安装时机;它不能“救活”一个本该在 require 的包

CI/CD 中 require-dev 的实际开关策略

CI 脚本里别无脑写 composer install。不同阶段要明确意图:单元测试需完整 require-dev,打包镜像则必须剔除。

  • github Actions 示例:
    run: composer install --no-interaction --prefer-dist --no-suggest

    → 缺少 --no-dev,导致测试工具打进生产镜像

  • 推荐分两步:
    测试阶段:用 composer install(默认含 dev)
    构建阶段:用 composer install --no-dev --optimize-autoloader
  • 如果你用 composer.lock 提交,要注意:即使某包只在 require-dev,它仍会记录在 lock 文件里;但 --no-dev 会跳过安装,lock 中的版本不会生效
  • 小陷阱:composer dump-autoload --optimize 在 dev 模式下会包含 autoload-dev 的路径,但线上运行时若没装 dev 包,这些路径就是无效的——所以线上务必用 --no-dev + --optimize-autoloader 一起跑

真正难的是厘清“这个类到底算不算运行时依赖”。很多人靠直觉放错位置,结果上线才暴露。与其反复修,不如每次加包前问一句:它会不会被 index.php 或控制器直接调用?

text=ZqhQzanResources