composer remove 不会自动清理冗余依赖,仅移除显式声明且无其他包复用的直接依赖;残留需靠 composer-unused 检测、手动排查配置/注解调用,并推荐重建 vendor 目录彻底清理。

composer remove 不会自动清理冗余依赖,它只删你明确指定的包,且仅当该包在 composer.json 中被显式声明时才生效。想靠它“一键瘦身”基本行不通。
为什么 composer remove 总是删不干净
它不是扫描工具,而是反向安装命令:只负责移除目标包及其未被其他任何已装包复用的直接子依赖。但以下情况它完全不管:
-
psr/log还在vendor/里?因为它正被symfony/consolerequire,composer remove monolog/monolog不会动它 - 你删了
guzzlehttp/guzzle,但guzzlehttp/promises残留——除非它只被 Guzzle 引用,否则不会被连带清除 -
composer remove默认不物理删除vendor/目录(尤其老版本或中断后),得靠后续composer install或composer update触发同步
真正能识别“冗余包”的只有 composer-unused
它静态扫描 src/、tests/、config/ 等目录里的 use、new、class_exists 调用,再比对 composer.json 的 require 和 require-dev,找出没被代码直接引用的包。但注意边界:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 它不分析配置文件中的字符串驱动(如
'driver' => 'some-package') - 不处理注解(如 Doctrine 的
@ORMEntity)、PHPStan 扩展、或服务提供者注册 - 运行前必须先装插件:
composer require --dev composer-unused/composer-unused - 执行
composer unused后,列表里标[unused]的才建议删,标[used]的别碰
composer remove 执行后必须补的三件事
命令退出成功 ≠ 清理完成。残留常藏在 autoload 映射、配置、或框架注册点里:
- 搜全项目:
grep -r 'SomePackage\Class' . --include="*.php",尤其检查config/、app/Providers/、routes/ - 删掉
config/app.php(Laravel)或config/app.php(ThinkPHP)里的服务提供者和别名 - 强制刷新自动加载:
composer dump-autoload -o;ThinkPHP 还要跑php think clear
最彻底的清理方式:重建 vendor/
当不确定哪些是历史遗留孤儿包时,重建比猜更可靠:
- 先确认
composer.json的require和require-dev已手动清空目标包(grep -n "package-name" composer.json双重验证) - 删掉整个
vendor/和composer.lock:rm -rf vendor composer.lock - 执行
composer install—— 它只装composer.json显式声明的包 + 它们必需的子依赖,所有“未声明也未被依赖”的包都会消失 - 对比旧
vendor.bak(如有)可直观看到哪些包被真正剔除
真正难的从来不是删包,而是那些没写在 composer.json 里、却活在配置或注解里的隐式调用——它们不会报错,直到某个请求路径走到那里才抛出 Class not found。

















