Composer本身不提供自动裁剪依赖树的能力,所谓裁剪本质是人工确认冗余包后,通过删配置、清锁文件、重装依赖实现,核心是仅按composer.json显式声明项重建vendor。

直接说结论:Composer 本身不提供“自动裁剪依赖树”的能力,所谓“裁剪”本质是人工确认 + 命令驱动的依赖重装,核心动作是删掉未被声明、也未被任何已声明包依赖的“孤儿包”。
composer remove 不会帮你裁剪依赖树
执行 composer remove vendor/package-name 只会移除你显式 require 的包,并更新 composer.json 和 composer.lock。它不会扫描整个依赖图,也不会顺手删掉那些“只被刚删掉的包所依赖”的子包(比如删了 monolog/monolog,psr/log 还在 vendor 里)。这常被误认为“没删干净”,其实是预期行为。
- 如果
composer remove报错Package ... is not required in your composer.json,说明它根本没出现在你的require或require-dev里,而是被其他包带进来的——此时不能靠remove清掉,得查谁在引用它 - 想确认某包是否真被间接依赖,用
composer depends vendor/package-name(旧版)或composer why-usage vendor/package-name(2.4+) - 执行成功后 vendor 目录仍有残留?大概率是 autoload 缓存没刷新,立刻跑
composer dump-autoload
真正裁剪依赖树得靠重装可信清单
最可靠、也最接近“裁剪”本意的操作,是彻底丢弃当前 vendor/ 和 composer.lock,仅按 composer.json 中明确列出的 require 和 require-dev 重新安装——所有未被声明、也未被这些声明包依赖的包,自然不会出现。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 先备份(可选):
mv vendor vendor.bak - 删干净:
rm -rf vendor composer.lock - 重装:
composer install(生产环境加--no-dev) - 对比
vendor.bak和新vendor,消失的那些就是“历史孤儿” -
别用
composer update替代:它会保留composer.lock里的旧包,哪怕它们早已没人需要
如何安全识别哪些包真能删?
光看 composer.json 不够,得结合代码实际使用情况。手动翻 src/、tests/、config/ 里的 use、类字符串、事件监听器、注解等太耗时,推荐分层验证:
- 先跑
composer show --tree,找叶子节点中只被已删包引用的包(比如某个psr/*包只出现在你刚remove掉的包的 require 列表里) - 再装插件
composer-unused/composer-unused,它会扫描src/和tests/下的use语句和类名硬引用,列出疑似冗余包 - 重点排查
symfony/polyfill-*、psr/*、doctrine/instantiator这类“看起来像工具但实为底层依赖”的包——它们常被核心组件悄悄 require,删错直接报Fatal error - 检查
composer.json的autoload.files和autoload.psr-4,删掉已不存在的路径映射,避免 autoload 扫描冗余目录
容易被忽略的细节:autoload 和锁文件的强耦合
裁剪后最常见的故障不是包没删干净,而是 autoload 映射没同步更新,或者锁文件残留旧约束。尤其当项目启用了 "optimize-autoloader": true,删包后不加 -o 参数跑 dump-autoload,运行时仍可能加载到旧类。
-
composer remove默认不触发dump-autoload,必须手动补上;CI 部署脚本里务必包含这步 - 删完重装后,如果
composer show还列出某个包,说明它仍在composer.lock中被其他包 require,不是孤儿 - 不要手动编辑
vendor/composer/autoload_*.php文件——这些是自动生成的,改了下次dump-autoload就被覆盖

















