生产环境必须加 --no-dev,否则会安装 phpunit 等 dev 包,浪费空间、增加安全风险并引发 autoloader 错误;应组合使用 --no-dev --optimize-autoloader --no-interaction,但需先确认无 runtime 依赖 dev 包。

生产环境部署时,composer install --no-dev 是必须加的,不加就可能把测试、调试用的包(比如 phpunit、laravel/pint、symfony/var-dumper)一起装进去,既浪费空间又增加安全风险。
为什么 --no-dev 不是默认行为
Composer 默认安装所有依赖,因为本地开发需要 require-dev 里的工具链。但生产环境不需要这些——它们不参与运行逻辑,只服务开发流程。跳过它们能减少约 30%~60% 的 vendor 体积,也能避免因 dev 包引入的额外 autoloader 或扩展依赖导致的启动慢、内存溢出等问题。
常见错误现象:composer install 后发现 vendor/bin/phpunit 存在、composer dump-autoload -o 报错说找不到 Mockery 类(其实它只该在测试时加载)。
- 只要不是本地写代码、跑测试,就该加
--no-dev - CI/CD 流水线里部署到 staging 或 prod 环境前,必须显式加这个参数
- 如果项目用了
autoload-dev,不加--no-dev会导致这些路径也被加入自动加载器,影响性能
composer install --no-dev 和 composer install --optimize-autoloader 的关系
两者解决不同问题,但常一起用:--no-dev 控制装哪些包,--optimize-autoloader(或简写 -o)控制怎么加载已装的包。后者会生成扁平化的 classmap,跳过 PSR-4 的文件扫描,对生产环境有明显提速。
使用场景:Docker 构建镜像、云函数冷启动、高并发 Web 服务。
- 单独用
--no-dev不够,建议组合:composer install --no-dev --optimize-autoloader --no-interaction -
--no-interaction防止交互式提示卡住自动化流程 - 注意:若项目用了
classmap且含 dev 目录(比如tests/),加了--no-dev后--optimize-autoloader会自动排除这些路径,无需手动清理
哪些情况不能简单加 --no-dev
不是所有“生产环境”都适合一刀切。有些场景下,require-dev 里的包实际被 runtime 依赖了,硬加 --no-dev 会导致运行时报错。
典型错误现象:Class 'NunoMaduro\Collision\Adapters\Phpunit\CollisionPrinter' not found(说明某命令行工具偷偷引用了 dev 包)、Laravel 的 php artisan tinker 在生产环境意外启用后报错。
- 检查
composer.json中是否误把运行时依赖写进了require-dev(比如某些 SDK、CLI 工具) - 运行
composer show --dev列出所有 dev 包,逐个确认用途;重点看有没有被bin目录脚本或 Artisan 命令直接 require - 若必须保留个别 dev 包,可用
composer install --no-dev --with=phpunit,laravel/pint(Composer 2.5+ 支持)
真正麻烦的是那些没文档、靠约定、悄悄依赖 dev 包的框架插件或私有组件——它们不会报错,直到某个调试钩子被触发才崩。上线前最好在干净容器里跑一次 composer install --no-dev + 实际请求验证。










