执行 composer remove 后 vendor 仍存在,是因为该命令仅修改 composer.json 并卸载包,但不会自动清理残留文件;需配对运行 composer update 或 composer install 才能同步 vendor 目录。

composer remove 之后为什么 vendor 还在?
执行 composer remove vendor/package 只会删 composer.json 里的条目并卸载包,但不会自动清理残留的 vendor/ 子目录(尤其当该包被其他依赖间接引用过,或安装时用了 --no-dev 等非默认选项)。更常见的是:你手动删了 composer.json 里的 require 行,却忘了运行 composer install 或 composer update —— 此时 vendor/ 完全不会变化。
- 必须配对操作:改完
composer.json后,跑composer update vendor/package(精准卸载)或composer install(按锁文件重装) - 如果只是想清掉所有未声明的包,
composer install --no-dev不行,它只控制 dev 依赖;正确做法是先确保composer.json干净,再跑composer install - 留意
composer.lock:它可能保留已删除包的旧记录,导致vendor/里残留文件夹;此时应删掉composer.lock再composer install(仅限开发环境)
如何安全地批量清理未声明依赖
Composer 没有内置 “清理未声明包” 的命令,因为这会破坏依赖图完整性。所谓“没用的包”,往往只是当前项目没直接 require,但可能是某个 require 包的子依赖 —— 直接删会导致运行时报 Class not found。
- 先用
composer show --tree查看完整依赖树,确认某包是否真无任何上游引用 - 用
composer depends vendor/package反查谁依赖它;返回空才说明可安全移除 - 不要手动删
vendor/下的文件夹:Composer 不会感知,下次install可能跳过重装,造成不一致 - 若确定要清空整个 vendor(比如换 PHP 版本后),直接删
vendor/和composer.lock,再composer install—— 这比“清理”更可靠
composer dump-autoload 能不能代替清理?
不能。composer dump-autoload 只是重新生成 vendor/autoload.php 和类映射,不影响已安装的包文件本身。即使你删了 composer.json 里的依赖,只要没运行 update 或 install,那些包的代码仍躺在 vendor/ 里,autoload 文件也可能还包含它们的 PSR-4 映射(尤其是用 classmap 方式注册过的)。
- 执行
composer dump-autoload --optimize会把所有类路径写进vendor/composer/autoload_classmap.php,反而让残留包更难察觉 - 如果 autoload 出错(如
Class XXX not found),优先检查vendor/composer/autoload_*.php是否含已删除包的路径,而不是怀疑 autoload 命令本身 - 真正需要的是同步:改声明 → 更新锁 → 重装 vendor
CI/CD 中清理 vendor 的推荐姿势
CI 环境下最怕缓存污染,但盲目 rm -rf vendor 会影响构建速度。关键是区分「干净重装」和「增量更新」。
- 用
composer install --no-interaction --prefer-dist --optimize-autoloader,不加--no-dev除非明确不需要 - 如果 CI 缓存了
vendor/,务必同时缓存composer.lock;二者不匹配时,Composer 会警告并可能回退行为 - 避免在 CI 中运行
composer update:它会改composer.lock,导致本地与线上依赖不一致 - 想验证有没有冗余包?加一步
composer show --direct对比composer.json的 require 列表,脚本化检查即可
composer clear-cache 或第三方插件,都解决不了根本问题——cache 清的是下载包缓存,不是 vendor 里的已安装代码。










