线上直接运行 composer install(不加 --no-dev)会安装 phpunit、phpstan 等开发依赖,导致安全风险、扩展缺失报错、autoloader 污染及调试接口暴露;--no-dev 仅跳过安装不清理已存 dev 包,需配合 rm -rf vendor、校验 composer.lock 并执行 composer install --no-dev --optimize-autoloader --no-interaction --prefer-dist --classmap-authoritative 才真正安全。

线上直接运行 composer install(不加 --no-dev)会把 PHPUnit、PHPStan、Laravel Pint 这类开发期工具装进生产环境
为什么开发包不能上生产?
require-dev 里的包不是“多装几个文件”那么简单,它们可能:
- 触发自动注册的 ServiceProvider(比如
roave/security-advisories会在启动时做依赖冲突检查,但线上根本不需要这个逻辑) - 引入未启用的扩展依赖(例如
phpunit/phpunit声明需要ext-dom和ext-json,而你的生产 PHP 可能没开ext-dom,导致new DOMDocument()报错) - 污染 autoloader 映射:即使没调用,
vendor/composer/autoload_psr4.php里仍会保留"Tests\": "tests/"这类路径,autoload 查找范围变大,I/O 开销上升 - 暴露调试接口:某些包(如
symfony/debug-bundle)在未显式禁用时,可能让_profiler路由意外可访问
composer install --no-dev 真的够用吗?
不够——它只跳过安装,不清理已存在的 dev 包。常见陷阱:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 上次手动执行过
composer require --dev phpunit/phpunit,vendor/里已经存在 PHPUnit 文件;这次加了--no-dev,Composer 不会删它 -
composer.lock中记录的 dev 包版本可能和当前vendor/里残留的版本不一致,导致composer dump-autoload生成的 classmap 出现混杂映射 - 某些框架(如旧版 Laravel)的
AppServiceProvider里写了if (app()->environment('local')) { ... },但判断依据是APP_ENV环境变量——如果 dev 包里有代码主动改写这个变量,线上行为就不可控
生产部署该用什么命令?
真正安全的组合必须同时满足三个条件:清除、锁定、优化。
- 先清空
vendor/目录(不是靠--no-dev隐含清理) - 确保
composer.lock已提交且与当前 Git 分支/Tag 严格匹配(CI 流水线里要加git diff --quiet composer.lock校验) - 用完整参数:
composer install --no-dev --optimize-autoloader --no-interaction --prefer-dist - 额外建议:加
--classmap-authoritative(尤其当项目 PSR-4 结构稳定时),它会让 autoload 完全忽略文件系统扫描,只查autoload_classmap.php
最常被忽略的一点:你没法靠一条命令修复历史遗留问题。如果 vendor/ 里已经混入 dev 包,--no-dev 不会帮你擦干净——得先 rm -rf vendor,再跑 install。










