必须加 --no-dev,否则生产环境默认安装 phpunit 等 dev 包;它从解析阶段绕开 require-dev,不下载、不写入 vendor、不注册 autoload 映射,是生产部署的强制安全边界。

必须加 --no-dev,否则生产环境一定会装进 phpunit、php-cs-fixer、laravel-debugbar 这类包——不是“可能”,是默认就装。
为什么 composer install 默认装 dev 依赖
它不看你的 APP_ENV、不读 COMPOSER_DEV=0、也不管你是不是在服务器上跑。Composer 只认两样东西:composer.lock 文件里记了什么,以及你有没有传 --no-dev。lock 文件里只要存了 "packages-dev" 区块(绝大多数开发机生成的 lock 都有),composer install 就会把它们全拉下来,除非你明确说“别碰 dev 那部分”。
-
--optimize-autoloader(或-o)只优化自动加载速度,完全不跳过任何包 -
COMPOSER_NO_INTERACTION=1环境变量能跳过交互,但对依赖范围零影响 - 删掉
composer.json里的require-dev字段?本地开发就崩了,而且 commit 后别人也用不了测试工具
composer install --no-dev 到底做了什么
它不是“尽量不装”,而是从解析阶段就绕开 require-dev:不下载、不解压、不写入 vendor/、不注册它们的 autoload 映射(指 autoload-dev 下的路径不会出现在 vendor/autoload_static.php 中)。
- 生效前提是
composer.lock里仍有packages-dev记录——--no-dev不会报错,也不会删 lock 文件内容 - 如果 lock 文件里已经混进了
phpunit/phpunit,那说明上次composer update没加--no-dev,得先清理再重生成 - 它不影响
autoload-dev的路径声明本身——比如"Tests\": "tests/"还在vendor/autoload.php里,只是没装任何测试类库,class_exists('TestsFooTest')仍可能返回true(如果文件物理存在)
Docker 和 CI/CD 里最容易漏掉的三件事
自动化流程里一漏,镜像体积多出 20–50MB,启动变慢,还可能暴露调试入口。
- 别只写
RUN composer install --no-dev,要搭配RUN rm -rf vendor/ && composer install --no-dev --prefer-dist --optimize-autoloader --no-scripts,清缓存防复用 - CI 脚本中,
composer install前必须确认composer.lock是干净的:执行grep -q '"require-dev"' composer.lock && echo "lock is dirty" || echo "safe" - 多阶段构建时,build 阶段可以全量安装(含 dev),final 阶段只
COPY --from=builder /app/vendor /app/vendor,但 builder 阶段命令必须含--no-dev,否则 copy 过来的还是带 dev 的
--no-dev 和 --production 是啥关系
两者完全等价,Composer 2.0+ 文档明确写了 --production 是 --no-dev 的别名。但注意:--prod 这个缩写根本不存在,输进去会报 Unrecognized option: --prod。
- 日常建议统一用
--no-dev,语义清晰,新人一眼看懂 - CI 脚本里如果已有
--production,不必硬改,但新项目别再用它 - 它和
composer dump-autoload --no-dev不是一回事:dump-autoload --no-dev只删 autoload 映射,不删已安装的包;而install --no-dev是从源头就不让包落地
最常被忽略的一点:--no-dev 只控制“装不装”,不控制“能不能加载”。如果业务代码里硬编码引用了 Tests* 或 PhpCsFixer*,即使没装包,运行时也可能因 autoloader 路径存在而静默失败——得靠 class_exists() 或接口抽象来兜底,不能只信参数。











