composer原生命令不支持composer remove --dev a/b c/d批量删除,但可安全执行composer remove --dev phpunit/phpunit friendsofphp/php-cs-fixer behat/behat(空格分隔),2.5+支持原子性操作;遇“package is required by another package”需先composer depends查依赖链;删后必须运行composer install --no-dev重建vendor并composer dump-autoload -o清理autoload-dev残留。

直接删 require-dev 里的包,不等于项目真正瘦身——phpunit/phpunit 被删了,但 phpstan/phpstan 还在拉它;friendsofphp/php-cs-fixer 没了,laravel/pint 却悄悄续上了依赖链。真正的瘦身,是让 Composer 自己“松开”那些没被代码路径真正触达的包。
怎么批量删 dev 依赖又不翻车?
Composer 原生命令不支持 composer remove --dev a/b c/d 这种写法,但你可以安全批量执行:
-
composer remove --dev phpunit/phpunit friendsofphp/php-cs-fixer behat/behat—— 多个包名用空格分隔,不要加引号或逗号,2.5+ 支持原子性操作(全成功或全回退) - 如果某个包报错 “Package is required by another package”,说明它被其他已装包(比如
phpstan/phpstan)显式 require,不能硬删,得先查composer depends phpunit/phpunit - 删完立刻检查
composer.json的require-dev区块是否清空,别只信终端输出——有些版本在中断后会残留条目
删完 dev 包,为什么 vendor 里还有?
composer remove --dev 只改声明和锁文件,不主动删磁盘文件。残留是设计行为,不是 bug。必须补一步:
- 运行
composer install --no-dev(生产环境)或composer install(开发环境),强制按当前composer.json和composer.lock重建vendor/ - 别用
rm -rf vendor && composer install --no-dev—— 这会绕过 lock 文件校验,可能触发意外版本漂移 - 确认
vendor/composer/autoload_psr4.php里不再有tests/或stubs/等 dev-only 路径映射,否则 autoload 仍会加载已删包的类
中文项目特别容易漏掉的三类残留
中文项目常集成 Laravel、ThinkPHP 或自研框架,配置驱动和服务发现更隐蔽:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
config/logging.php、config/cache.php里硬编码的类名字符串(如'monolog/handler/stream'),composer-unused扫不出来,必须grep -r "monolog" config/ -
app/Providers/下注册的服务提供者(比如TelescopeServiceProvider),删了laravel/telescope却忘了注释掉AppServiceProvider里的$this->app->register(...) - 注解驱动的类(如 Doctrine ORM 的
@ORM\Entity、PHPStan 的@phpstan-ignore-next-line),它们引用的类可能来自已删的 dev 包,运行时才暴露
一个轻量但够用的清理脚本(可直接复制)
以下脚本适用于大多数 Laravel / ThinkPHP 中文项目,不依赖插件,只用 Composer 原生命令:
#!/bin/bash
# 清理无用 dev 依赖(需 Composer 2.5+)
DEV_PACKAGES=("phpunit/phpunit" "friendsofphp/php-cs-fixer" "behat/behat" "phpstan/phpstan")
<p>echo "正在移除 dev 依赖..."
for pkg in "${DEV_PACKAGES[@]}"; do
echo "→ 删除 $pkg"
if ! composer remove --dev "$pkg" --no-interaction 2>/dev/null; then
echo "⚠️ $pkg 被其他包依赖,跳过"
fi
done</p><p>echo "更新 vendor(仅保留生产依赖)..."
composer install --no-dev --no-interaction</p><p>echo "刷新 autoload 映射..."
composer dump-autoload -o</p><p>echo "验证完成:运行 composer show | grep -E '^(phpunit|php-cs-fixer|behat|phpstan)' 应无输出"</p>
脚本末尾那句验证命令,才是真正判断是否瘦下来的依据——别只看 vendor/ 目录大小,composer show 输出才是事实来源。最常被忽略的是 autoload-dev 字段没同步删,导致 tests/ 路径还在 autoloader 里挂着,一跑测试就报错。










