composer remove 后 vendor 仍有文件,是因为该命令仅删除 composer.json 条目并卸载包,不自动清理残留目录;尤其当包曾被间接依赖或安装时用了 --no-dev 等选项,且未配对运行 composer install 或 composer update 同步 vendor 目录。

Composer 没有“清理孤立包”的内置命令,所谓“孤立”往往只是你没看清依赖树——直接删 vendor/ 子目录会引发 Class not found。
为什么 composer remove 后 vendor 里还有文件?
执行 composer remove vendor/package 只做两件事:删 composer.json 里的 require 行、卸载该包。它不检查、也不清理 vendor/ 下残留的文件夹,尤其当这个包曾被其他依赖间接引入过,或你之前用过 --no-dev 等非默认选项安装。
- 更常见的情况是:你手动删了
composer.json的某行,却忘了运行composer install或composer update—— 此时vendor/完全不会变 - 如果想精准卸载,应配对使用:
composer remove vendor/package→composer install(按 lock 文件重装),或composer update vendor/package(只更新该包) -
composer.lock可能保留已删除包的旧记录,导致vendor/里残留文件夹;此时应先删composer.lock再composer install(仅限开发环境)
怎么判断一个包真没被任何依赖引用?
别猜,用 Composer 自带命令验证。所谓“没用”,90% 是误判——它可能是某个 require 包的子依赖,删了就 Class not found。
- 查依赖树:
composer show --tree,看目标包是否出现在任意分支下 - 反查谁依赖它:
composer depends vendor/package,返回空才说明可安全移除 - 不要手动删
vendor/vendor/package:Composer 不会感知,下次install可能跳过重装,造成类加载路径和实际文件不一致
composer dump-autoload 能不能清掉残留包?
不能。这个命令只重新生成 vendor/autoload.php 和类映射文件,不影响已安装的包代码本身。
- 即使你删了
composer.json里的依赖,只要没跑composer install或composer update,那些包的代码仍躺在vendor/里 -
vendor/composer/autoload_classmap.php(尤其是dump-autoload --optimize生成的)可能还包含已删除包的路径,反而让残留更难察觉 - 如果 autoload 报错(如
Class XXX not found),优先检查vendor/composer/autoload_*.php是否含已删除包的路径,而不是怀疑dump-autoload命令本身
真正安全的“清空重来”方式是什么?
与其纠结“清理孤立包”,不如直接重建依赖树——这是最可靠、也最省时间的做法,尤其当你换 PHP 版本、切镜像源、或长期没维护项目时。
- 删掉整个
vendor/目录和composer.lock文件 - 确认
composer.json已清理干净(无误删、无冗余 require) - 运行
composer install,从头生成锁文件并安装 - CI/CD 中务必加
--no-interaction,避免卡在交互提示
容易被忽略的是:composer.lock 才是决定装什么的最终依据,不是缓存、不是 vendor 目录、也不是你脑子里记得的“应该装新版”。清缓存、删 vendor、甚至重装 PHP,都不如删 lock 文件再 install 来得彻底。











