正确命令是 composer install --no-dev,它仅安装 require 中的包且依赖 composer.lock;误用 --dev=false 等无效参数会导致 dev 包被安装;需配合 --optimize-autoloader 并注意 autoload-dev 的污染问题。

composer install 时跳过 dev 依赖的正确命令
直接用 composer install --no-dev,这是唯一可靠、被 Composer 官方支持的方式。它会读取 composer.lock 文件,只安装 require 中的包,完全忽略 require-dev 里的内容。
常见错误是误用 composer install --dev=false 或 --without-dev —— 这些参数根本不存在,Composer 会报错或静默忽略,导致 dev 包照常安装。
- 必须确保项目已有
composer.lock,否则--no-dev不生效(Composer 会退回到install的默认行为,即装全量) - 如果想从头生成一个不含 dev 的 lock 文件,得先删掉现有
composer.lock,再运行composer install --no-dev --no-interaction -
--no-dev对composer update同样有效,但更新后生成的composer.lock就不再包含 dev 包的版本约束了
为什么 vendor/autoload.php 里还会加载 dev 类?
即使用了 --no-dev,某些类仍可能被自动加载,不是因为包被装进来了,而是因为 autoload-dev 的映射被写进了 vendor/composer/autoload_static.php —— 这是 Composer 的设计缺陷:它把 dev autoload 配置也编译进主自动加载器里了。
典型现象是:代码里没引用任何 dev 包,但运行时却抛出 Class 'PhpUnit\Framework\TestCase' not found 以外的奇怪类找不到错误,或者测试辅助类意外被加载。
- 检查
vendor/composer/autoload_static.php,搜索autoloadDev字段,确认是否混入了 dev 的 PSR-4 映射 - 临时解决:在生产环境部署后手动删掉
vendor/composer/autoload_static.php,再运行composer dump-autoload --optimize - 根治办法:把所有 dev 相关的 autoload 配置从
composer.json的autoload-dev移到require-dev的包内部,不要放在主项目配置里
CI/CD 或 Docker 构建中怎么安全落地?
别信“先 install 再删 vendor/bin/phpunit”这种土办法。真正稳定的流程是分两步:构建阶段用 --no-dev,且全程不碰 composer.json 里的 require-dev 字段。
- Dockerfile 里写死:
RUN composer install --no-dev --no-interaction --optimize-autoloader - CI 脚本中避免混合使用
update和install:如果本地开发用composer update,上线前必须用install --no-dev重建,不能靠缓存 vendor 目录 -
--optimize-autoloader必须加,否则自动加载性能下降明显,尤其在 Laravel/Symfony 这类大量使用 PSR-4 的框架里 - 注意:某些私有包若把测试工具写在
autoload而非autoload-dev,也会被带进生产环境——得去对应包的composer.json里改
composer create-project 怎么默认不装 dev 依赖?
没有内置开关。composer create-project 默认行为就是完整安装(含 dev),哪怕目标项目 lock 文件本身不含 dev 包,它也会根据 composer.json 重新生成一份含 dev 的 lock 并安装。
所以不能依赖 create-project 一步到位,必须拆成两步:
- 先
composer create-project --no-install xxx(跳过安装) - 再进目录,删掉
composer.json里的require-dev段(或清空),然后composer install --no-dev - 更稳妥的做法:用
git clone+composer install --no-dev替代 create-project,尤其在部署脚本里
这个环节最容易被忽略的是 lock 文件来源——如果项目没提交 lock 文件,create-project 生成的 lock 就天然带 dev,后续怎么加 --no-dev 都没用。










