不会。composer remove 仅卸载显式指定的包,不清理未被其他包依赖的“孤儿依赖”;需用 composer-unused 插件扫描代码引用关系来安全识别并删除冗余包。

composer remove 会自动清理未被引用的依赖吗?
不会。执行 composer remove 只卸载你明确列出的包,不会顺手删掉它们间接拉进来的、但当前项目已不再需要的“孤儿依赖”。比如你删了 monolog/monolog,它之前带进来的 psr/log 可能还在 vendor/ 里躺着——只要别的包还声明依赖它,Composer 就认为它“有用”。
真正要瘦身,得靠 Composer 自己的依赖解析逻辑,而不是人工猜哪些能删。
怎么安全识别并删除真正的冗余包?
用 composer unused(需先装插件)是最直接的办法。它会扫描你的代码(src/、tests/ 等),比对 composer.json 里声明的所有 require 和 require-dev 包,找出那些:
- 没被任何 use 语句引用
- 没在字符串中被动态加载(如 class_exists('Some\Class') 这类不算,插件默认不分析)
- 不是其他已保留包的必需依赖
操作步骤:
- 运行
composer require --dev composer-unused/composer-unused - 执行
composer unused,它会列出疑似冗余的包名 - 逐个确认——尤其注意是否在配置文件、事件监听器、或注解(如 Doctrine、PHPStan)中被隐式使用
- 对确认无用的包,用
composer remove vendor/package-name删除
为什么不能直接删 vendor/ 下的文件或手动改 composer.json?
手动删 vendor/ 文件会导致 autoloader 失效、CI 报错、甚至本地 composer install 失败;直接删 composer.json 里的条目却不跑 composer remove,下次别人 composer update 又会把包拉回来,还可能因依赖冲突报错。
关键点在于:Composer 的锁机制和 autoload 生成都强依赖 composer.lock 和命令驱动的变更流程。绕过命令等于绕过一致性校验。
常见翻车场景:
- 删了 phpunit/phpunit 却忘了它被 phpstan/phpstan 作为 dev 依赖引用 → composer update 时 PHPStan 报错
- 误判 symfony/polyfill-* 是冗余 → 实际被核心组件悄悄 require,删掉后 PHP 低版本运行时报 Fatal error
有没有轻量级替代方案(不装插件)?
有,但精度低、适合小项目快速筛查:
- 用
composer show --tree看依赖树,找只被已删包引用的叶子节点(例如某psr/*包只出现在刚删掉的包的 require 列表里) - 临时清空
vendor/,再跑composer install --dry-run,观察哪些包没被安装——说明当前项目没显式或隐式需要它 - 检查
composer.json的autoload和autoload-dev,删掉已不存在的psr-4映射路径,避免 autoload 冗余扫描
这些方法不保证 100% 安全,尤其对用了反射、DI 容器或注解驱动的项目,容易漏判。真要瘦身,还是推荐走 composer-unused 流程。
最常被忽略的是:测试工具链(如 Pest、Codeception)和静态分析工具(PHPStan、Psalm)本身会引入大量 dev-only 依赖,它们不参与运行时,但一旦删错,CI 就卡在第一步。别只盯着 prod 依赖看。










