默认情况下 composer install 会安装 require 和 require-dev 全部依赖,因 composer 无环境识别能力;必须加 --no-dev 的场景包括线上部署、docker production 构建及 ci/cd 部署阶段。

composer install 为什么装了 dev 依赖?
默认情况下 composer install 会安装 require 和 require-dev 里的全部包,哪怕你只是上线部署——这不仅拖慢速度,还可能引入测试工具、调试器等不该出现在生产环境的代码。
根本原因是 Composer 没有“自动识别环境”的能力,它只看 composer.json 和本地 composer.lock,不会读取 APP_ENV 或服务器角色。
--no-dev 是什么,什么时候必须加?
--no-dev 是 composer install 和 composer update 的开关,作用是跳过 require-dev 区块里的所有依赖,只装 require 列表。
以下场景不加就容易出问题:
- 线上服务器部署时,用
composer install --no-dev(不是update) - Docker 构建阶段,在
production镜像里避免打包phpunit、phpstan等 - CI/CD 流水线中区分构建(需要 dev)和部署(不需要 dev)两个阶段
常见错误:--no-dev 没生效?检查这几点
加了参数却还是装了 phpunit 或 symfony/debug-bundle?大概率是这些原因:
- 执行的是
composer update而非install——update默认忽略--no-dev对 lock 文件的影响,且可能因依赖树间接拉入 dev 包 -
composer.lock里原本就记录了 dev 包(比如之前在本地跑过 full install),而install严格按 lock 执行;此时需先删 lock 或确认 lock 是否由--no-dev生成 - 某些包把“开发时必需”写进了
require(比如把laravel/pint放错位置),--no-dev压根不管它 - 用了
COMPOSER_NO_DEV=1环境变量但没导出(bash 中需export COMPOSER_NO_DEV=1)
生产环境推荐的最小安全命令组合
别只记 --no-dev,配套动作缺一不可:
- 部署前确保
composer.lock是用--no-dev生成的(或至少不含 dev 包):本地运行composer install --no-dev --optimize-autoloader - 线上执行:
composer install --no-dev --optimize-autoloader --no-interaction - 如果项目用 autoloader classmap,加
--classmap-authoritative可进一步提速,但要求所有类路径必须可静态分析(多数 Laravel/Symfony 项目没问题) - 禁用脚本执行:
--no-scripts(防止post-install-cmd里调用 dev 工具)
真正麻烦的不是参数本身,而是 lock 文件是否干净、是否被多人共用、是否混入了本地开发时的临时修改——这些比记命令更容易翻车。










