直接删除 vendor//readme.md 会出问题,因为某些包(如 monolog/monolog)在运行时动态 include readme.md 中的示例代码作为配置模板或初始化片段,硬删将导致 include 失败或 class not found;安全清理需配合 composer-archive-excludes(安装阶段过滤)和 vaimo/composer-cleaner(安装后按白名单清理),并正确配置路径匹配规则(如 "/readme."、"/tests/" 等),且必须重建 vendor 和 lock 文件后执行清理。

为什么直接删 vendor/*/README.md 会出问题?
因为有些包(比如 monolog/monolog)在运行时会动态 require 或 include README.md 里的示例代码——不是文档用途,而是作为配置模板或初始化片段。硬删会导致 Warning: include(): failed to open stream 或 Class not found。更麻烦的是,这类行为不会在 composer install --no-dev 中暴露,只在线上首次请求时触发。
怎么安全地批量清理 README/Tests?
不能靠 find vendor/ -name "README.*" -delete 这类暴力命令。正确做法是分两层控制:
- 安装阶段跳过:用
composer-archive-excludes插件,在 zip 解压时就过滤掉/README.md、/tests/等路径 - 安装后清理:用
vaimo/composer-cleaner插件,按白名单路径 unlink,不碰 autoload 映射
两者必须配合使用:前者防“落地”,后者清“残留”。单独用任一方案都可能漏掉私有包或旧版包里的非标准路径(如 docs/README.txt)。
插件配置要写对路径匹配规则
vaimo/composer-cleaner 的 exclude 是从每个包根目录开始匹配的,开头斜杠表示绝对路径片段,不是文件系统路径。常见错误是写成 "vendor/*/README.md" 或漏掉大小写变体。
- 正确写法(兼容多数包):
"/README.md"、"/readme.md"、"/README.*" - 测试目录要覆盖大小写和复数:
"/tests/"、"/Tests/"、"/test/" - 别加
vendor/前缀——插件自动遍历所有已安装包的根目录
配置示例(写在项目 composer.json 的 extra 下):
"extra": {
"cleaner": {
"exclude": [
"/README.*",
"/CHANGELOG.*",
"/LICENSE.*",
"/tests/",
"/Tests/",
"/test/",
"/.github/",
"/.git/"
]
}
}
中文环境要额外处理语言包和翻译目录
中文 README 和 Tests 通常混在 /translations/、/lang/、/locale/ 里,但不同包存放位置差异极大。比如 monolog/monolog 把翻译逻辑实现在 src/Monolog/Translator/,删了就丢功能;而 symfony/translation 的中文资源真在 translations/zh_CN/ 下。
- 先查清路径:
ls -F vendor/monolog/monolog/src/Monolog/ | grep -i trans - 再精准排除:
"/src/Monolog/Translator/"加进exclude数组 - 不要全局删
/translations/——doctrine/dbal的命令行帮助文本也藏在里面
真正起效的前提是:先 rm -rf vendor composer.lock,再 composer install --no-dev --prefer-dist --optimize-autoloader --classmap-authoritative,最后跑 composer cleaner。跳过重建步骤,清理只是擦边,旧文件还在。











