composer archive 命令不可用且不处理 vendor 目录,真正生效的是 composer-archive-excludes 插件配合 config.archive.excludes 在解压时过滤路径,再结合 --classmap-authoritative 优化自动加载。

composer archive 命令根本不能用——它不是用户可用命令,执行必报 Command "archive" is not defined。你想通过它来“排除 vendor 中的测试用例”,方向错了。
为什么 composer archive 对 vendor 无效
这个命令只在 Packagist 构建分发包、或你作为包作者运行 composer pack(Composer 2.5+ 实验性)时内部调用;它从不处理已安装的 vendor/ 目录,也不影响 composer install 行为。你看到的“排除测试文件”效果,实际来自解压阶段的过滤,不是归档命令本身。
archive.excludes 配置只对 zip 包解压生效
真正起作用的是社区插件 composer-archive-excludes + config.archive.excludes,它在 unzip 时跳过指定路径,让 /tests/、/docs/ 根本不落地:
- 先装插件:
composer require --dev composer-archive-excludes - 在
composer.json的config块里加:"archive": { "excludes": ["/tests/", "/docs/", "/examples/", "/.github/", "/CHANGELOG.md"] } - ⚠️ 路径必须以
/开头,且不支持**或通配符;写成"tests"或"Tests"不匹配 - 该配置仅对从 Packagist 下载的 zip 包生效,git clone 方式完全无视它
删 vendor 里的 tests/ 是高危操作
别用 find vendor -name tests -type d -exec rm -rf {} + ——这不是优化,是埋雷:
- 旧版
monolog/monolog的tests/里放着StreamHandler示例类,删了直接Class not found - 某些包(如
symfony/console)把测试放在独立目录,能被archive.excludes过滤;但若混在src/里,插件也无能为力 -
autoload-dev只控制自动加载,不控制文件是否下载——配了它,tests/照样进vendor/
--classmap-authoritative 才让瘦身真正生效
前面所有操作只是“删文件”,但 PHP autoloader 默认仍会 scandir() 整个 vendor/ 目录找类。哪怕 tests/ 已被跳过,扫描失败也会在容器、NFS 或只读文件系统上引发加载异常:
- 确保
composer.json含"optimize-autoloader": true - 运行:
composer dump-autoload --optimize --classmap-authoritative --no-dev - 后续安装必须带参数:
composer install --no-dev --optimize-autoloader --classmap-authoritative - 这步不减体积,但决定前面所有清理会不会白做——最容易被忽略的点就在这儿
真正吃空间的是包内部的 tests/、.git 和 docs/,不是你项目根目录下的测试文件;而 vendor 目录的“瘦身”,核心永远是“不装”,不是“后删”。











