真正安全、可复现、CI友好的vendor精简方式只有三类:跳过开发依赖(--no-dev)、强制dist模式(--prefer-dist --remove-vcs)、启用类映射权威模式(--classmap-authoritative);配合archive.excludes插件在解压时过滤tests/docs等路径。

精简 vendor 目录不是靠手动删 tests/ 或 docs/,而是控制安装行为本身——真正安全、可复现、CI 友好的方式只有三类:跳过开发依赖、强制 dist 模式、启用类映射权威模式。
用 --no-dev 跳过 require-dev 里的包
这是最直接有效的一步。线上环境根本不需要 phpunit、phpstan、mockery,但默认 composer install 全部拉下来,体积多出 30%~60% 很常见。
-
composer install --no-dev必须在部署前执行;CI/CD 流水线漏掉它,后续所有优化都白搭 -
--no-dev不影响autoload-dev的 PSR-4 映射声明,但那些包压根不会被下载和解压,所以实际 autoload 不会加载它们 - 如果项目用了
require-dev中的二进制(如php-cs-fixer),得把它挪到require,或改用全局安装,否则命令会报错
加 --prefer-dist --remove-vcs 强制走压缩包并清理元数据
默认 composer install 可能对某些包走 git clone,保留完整 .git 目录;dist 包则已剔除 tests/、docs/、.github/ 等非运行时内容。
-
--prefer-dist强制优先下载 zip 包,不是 clone 仓库 -
--remove-vcs是兜底项:有些 dist 包里仍混着.git,这个参数会在解压后自动删掉 - 注意:必须用
install,不是update—— 只有install才按composer.lock重新拉取并裁剪 - 已有
vendor不会自动更新,需先rm -rf vendor再重装
配 archive.excludes 在解压阶段过滤特定路径
--no-dev 和 --prefer-dist 解决不了包内部的 tests/ 目录——因为这些目录是作者打包进 zip 的。要真删,得在解压时跳过。
- 先装插件:
composer require --dev composer-archive-excludes - 在
composer.json的config.archive.excludes下加过滤项:["/tests/", "/docs/", "/examples/", "/.github/", "/CHANGELOG.md"] - 之后每次
install或update,这些路径在 unzip 阶段就被跳过,不会落地 - ⚠️ 别用
find vendor -name tests -type d -exec rm -rf {} +:旧版monolog等包把 handler 示例放tests/下,删了会导致Class not found
启 --classmap-authoritative 关闭文件扫描
这步不减体积,但让前面所有瘦身真正生效——否则即使删了 tests/,autoloader 仍可能因 scandir() 失败而报错,尤其在容器、NFS 或只读文件系统上。
- 确保
composer.json的config里有"optimize-autoloader": true - 运行:
composer dump-autoload --optimize --classmap-authoritative --no-dev - 后续
composer install --no-dev --optimize-autoloader --classmap-authoritative会重建vendor并只保留vendor/composer/autoload_classmap.php里声明的路径 - 这个 classmap 是静态生成的,完全绕过动态扫描,也避免因目录缺失引发 autoload 异常
最容易被忽略的是:vendor/bin 下的脚本只是小包装器,删它们没用;真正占空间的是包自身的 src/、嵌套 vendor/、.git/ 和 tests/。盯住这三处,比事后压缩或手动删文件靠谱得多。


















