Composer怎么清理未使用的包 清除多余依赖操作指南【方法】

9次阅读

composer remove 不会自动清理间接依赖,仅删除无任何包引用的顶层依赖;需用 composer why 检查引用关系,确认无依赖后执行 remove –no-update 再统一 update。

Composer怎么清理未使用的包 清除多余依赖操作指南【方法】

composer remove 会自动处理依赖关系吗

不会。执行 composer remove vendor/package-name 只会移除指定包及其在 composer.json 中的声明,但不会主动清理它曾经引入、但当前其他包仍依赖的“间接依赖”。真正被删掉的,仅是那些已无任何包(包括你的项目代码和其余已安装包)引用的顶层依赖及其子树。

常见错误现象:运行 composer remove monolog/monolog 后,composer show 里还看到 psr/log 留着——因为它正被 symfony/console 依赖着,不是“未使用”,只是你没直接 require 它。

  • 判断是否真“未使用”:先跑 composer why psr/log,看谁在用它;如果输出为空,才说明可安全清理
  • 想批量查孤儿包?没有内置命令,但可用 composer show --tree | grep -v "├──|└──" 辅助筛选(不严谨,仅作初筛)
  • 别手动删 vendor/ 下文件或改 composer.lock,这会导致状态不一致,下次 composer install 可能失败

composer update –with-dependencies 不等于清理

这个参数常被误解为“清理冗余依赖”,其实它只控制更新范围:composer update foo/bar --with-dependencies 表示“更新 foo/bar,同时更新它所有直接依赖(哪怕版本没变)”,和删除完全无关。

真正影响依赖图收缩的操作只有两个:removeupdate(后者通过版本约束收紧间接触发淘汰)。比如把 "guzzlehttp/guzzle": "^7.0" 改成 "^7.2" 并运行 composer update guzzlehttp/guzzle,可能让旧版 ralouphie/getallheaders 被新版 Guzzle 的更严格依赖声明踢出图谱。

  • 想靠 update 清理?先检查 composer.json 里的版本约束是否过于宽松(如 "*""^1.0 || ^2.0"
  • 运行 composer update --dry-run 预览变更,重点关注 “Removing” 行——那是真正会被删的包
  • composer update 默认不降级,所以即使某个包已无用,只要锁文件里有且满足约束,就不会被删

如何识别并删除真正的“未使用包”

核心逻辑:一个包属于“未使用”,当且仅当它既不在 composer.jsonrequire / require-dev 中,也不被任何已安装包的 composer.json 声明为依赖(含 require-dev,但注意 dev 依赖在生产 install 时默认不加载)。

实操分三步:

  • 运行 composer show --installed 列出所有已装包
  • 对每个包执行 composer why ;若返回 “Did not find package in any registered root dependencies”,说明它没被任何根依赖或其传递依赖引用 → 可删
  • 确认后执行 composer remove --no-update(加 --no-update 避免连锁更新干扰判断),再统一 composer update

注意:composer why 在某些旧版 Composer(如 1.x)中不支持,需升级到 2.2+;若无法升级,可临时用 composer depends (Composer 2.5+ 新增)替代。

dev 依赖残留特别容易被忽略

很多项目把测试工具(如 phpunit/phpunit)、静态分析(如 phpstan/phpstan)放在 require-dev,但重构后忘了删。它们不会出现在生产环境 vendor/(如果用了 --no-dev),但仍在本地 composer.json 里占位,且 composer why 默认不查 dev 依赖链。

查 dev 包是否真被需要:

  • -D 参数: composer why -D phpunit/phpunit
  • 或者直接删掉 require-dev 条目,再跑 composer install --dry-run,看是否报错缺失依赖
  • CI 脚本里如果用了 --no-dev,那所有 require-dev 包本就不该影响运行时,可放心清理

最麻烦的是那种“被注释掉的 require”或“写在 README 里但没进 composer.json”的包——它们根本不会出现在 vendor/,也无需清理,但容易让人误以为是“残留”。盯紧 composer.jsoncomposer.lock 两个文件,才是真实依据。

text=ZqhQzanResources