composer install 默认安装dev依赖是因为未指定--no-dev参数,它会加载require-dev中的包;加--no-dev可跳过dev依赖、减小vendor体积30%~70%,并避免运行时冲突,需配合-o优化自动加载。

composer install 为什么默认装了 dev 依赖
因为 composer.json 里没明确告诉 Composer:现在是上线环境,只装正式依赖。它默认按开发场景处理,把 require-dev 里的包(比如 phpunit、friendsofphp/php-cs-fixer)一并拉下来——哪怕你只是想部署到服务器跑个 API。
用 --no-dev 才能真正跳过 dev 依赖
执行安装时加这个参数,Composer 就会忽略 require-dev 区块,也不加载 autoload-dev 配置,生成的 vendor/ 目录体积通常能小 30%~70%,且避免因 dev 包引入额外 autoloader 或扩展依赖导致的运行时冲突。
常见错误现象:composer install 后线上报错 Class 'PhpCsFixer\Finder' not found,其实是误装了 dev 工具又没配好 autoload;或者部署后内存溢出,查发现 roave/security-advisories 这类 dev-only 包被加载进生产流程。
- 必须配合
--no-dev使用--optimize-autoloader(即-o),否则自动加载仍可能慢一截 - CI/CD 脚本里别漏掉,尤其在
composer install前删过vendor/或composer.lock - 如果项目用了
config.platform模拟低版本 PHP,记得它对--no-dev无影响,但会影响包解析结果
导出生产包前先确认 lock 文件是否干净
composer.lock 是安装依据,但它本身不区分 dev/non-dev —— 它记录了所有已解析包的版本和哈希。所以关键不是锁文件“有没有 dev”,而是你用什么参数去读它。
容易踩的坑:git checkout 切分支后直接 composer install --no-dev,结果装出一堆旧版 dev 包。原因:lock 文件里还存着上个分支的 require-dev 记录,而 Composer 在 --no-dev 模式下会照常解析这些条目(只是不装),但如果 lock 文件混乱,可能触发意外的依赖回退或版本漂移。
- 上线构建前建议先
composer update --no-dev -o,强制刷新 lock 中非 dev 部分 - 若用 Docker,
COPY composer.json composer.lock ./后立刻composer install --no-dev -o,别让中间步骤污染 vendor - 检查 lock 文件是否含 dev 包:grep -q '"require-dev"' composer.lock && echo "warning: dev section exists" || echo "clean"
PHP 版本与 platform 配置会影响 --no-dev 行为吗
不影响是否跳过 dev 依赖,但会影响哪些包能被选中。比如你在 config.platform.php 设为 "8.1",而某 dev 包只支持 PHP 8.2+,那即使加了 --no-dev,Composer 解析主依赖时也可能因平台约束收紧,间接导致某个生产包降级到不兼容版本。
典型表现:本地 composer install 正常,服务器用 --no-dev 却报 symfony/console v6.4 requires php >=8.1.0,查发现 lock 文件里该包被锁定为 v5.x,原因是 platform 设置让 Composer 回退了整个依赖树。
- platform 配置应严格匹配目标环境 PHP 版本,而非开发机版本
- 运行
composer show --platform确认当前生效的 platform 值 - 如需彻底隔离环境差异,可在构建命令中临时覆盖:
COMPOSER_PLATFORM_CHECK=0 composer install --no-dev -o










