composer install --no-dev 是清理 dev 依赖的起点而非终点,它仅跳过安装 require-dev 包,不删除已存在残留、不更新 autoload 映射、不清理配置文件中硬编码的服务提供者或路径。

composer install --no-dev 是清理 dev 依赖的起点,但不是终点
直接运行 composer install --no-dev 确实能跳过 require-dev 中声明的包(比如 phpunit/phpunit、friendsofphp/php-cs-fixer),但它只影响“安装行为”,不清理已存在的残留。常见错误是删完后 vendor/ 里还躺着一堆测试类、配置文件甚至完整源码树。
- 它不会删除
vendor/下已存在但不再被composer.lock记录的 dev 包目录(比如你之前装过behat/behat,后来手动删了composer.json里的条目,但没跑 install) - 它不触碰
autoload-dev映射——如果某个包的tests/路径仍被 autoload 映射着,即使包本身不在vendor/里,dump-autoload仍可能加载空路径或报错 - 某些包(如
laravel/pint)会把自身作为 dev 依赖,同时又通过extra.laravel.pint配置隐式拉取其他工具,--no-dev不管这种间接依赖
必须补上 dump-autoload --classmap-authoritative 才算真正切断 autoload
很多项目(尤其是 Laravel 9+)启用了 --classmap-authoritative 模式,这意味着自动加载器只查 vendor/composer/autoload_classmap.php,完全跳过文件系统扫描。删了包但没刷新 classmap,旧类名依然能 new 出来,或者启动时报 Class not found 却搜不到引用——其实是映射没更新。
- 执行
composer dump-autoload --classmap-authoritative -o强制重生成 classmap,并剔除所有未被 autoload 规则覆盖的路径(包括tests/、examples/、stubs/) - 检查
vendor/composer/autoload_psr4.php和autoload_classmap.php,确认里面没有指向已删包的命名空间或路径 - 如果项目用了自定义
autoload.files或autoload.psr-4,手动删掉其中硬编码的 dev-only 路径(比如"Tests\": "tests/"),再跑 dump
验证是否真清干净:别信 vendor 目录大小,要看 composer show 和 grep
光看 vendor/ 目录体积下降没用——有些包删了但 autoload 还挂着路径,或者 config 文件里留着服务提供者注册,照样让 CI 失败。
- 运行
composer show phpunit/phpunit,返回Package not found才算成功;若还显示版本号,说明composer.json或composer.lock没清干净 - 用
grep -r "PHPUnit\Framework" . --include="*.php"检查代码里是否还有残留引用(尤其注意tests/目录和phpunit.xml配置) - 搜索框架配置文件:
grep -r "ServiceProvider" config/ app/Providers/ --include="*.php",删掉对应注册行(如LaravelSanctumSanctumServiceProvider::class) - 运行
composer install --no-dev --no-scripts后再php artisan config:clear(Laravel)或php think clear(ThinkPHP),避免缓存掩盖问题
一键脚本要防坑:别用 rm -rf vendor + install,锁文件哈希会失效
有人写脚本 rm -rf vendor && composer install --no-dev 图省事,但这是高危操作——它绕过了 composer.lock 的哈希校验,可能触发版本漂移(尤其当 lock 文件里有 dist.shasum 时)。Composer 2.5+ 的 install 默认校验 lock,但强制删 vendor 后,它可能 fallback 到最新兼容版。
- 正确顺序是:先
composer remove --dev xxx yyy(批量删声明),再composer install --no-dev(按 lock 重建) - 如果
composer.json里require-dev已为空,直接composer install --no-dev就够了;但务必确认composer.lock的packages-dev数组为空 - CI 环境中加
--no-cache参数:composer install --no-dev --no-cache --optimize-autoloader --classmap-authoritative,避免镜像源污染或缓存脏数据
composer install --no-dev 自动消失,得人眼确认。


















