vendor体积大根本原因是PHP包默认打包了测试、文档、多语言等冗余文件,--no-dev和--optimize-autoloader仅跳过dev依赖并优化加载逻辑,无法删除包内非运行必需内容;需通过--prefer-dist、archive.excludes、post-install-cmd脚本或专用工具按需裁剪。

vendor 文件夹为什么动辄上百 MB?
根本原因不是 Composer 本身有问题,而是很多 PHP 包(尤其是 Laravel、Symfony 生态)默认把测试文件、文档、示例、本地化语言包(lang/、resources/lang/)、甚至前端构建产物(dist/、build/)一并打包进 dist 发布。比如 laravel/framework 的 lang/ 目录就含 40+ 种语言,占几 MB;symfony/translation 自带全部 ICU 数据;monolog/monolog 的 tests/ 和 doc/ 在生产环境毫无用处。
composer install --no-dev --optimize-autoloader 还不够
这能删掉 dev-dependencies 和生成优化的 autoload_classmap.php,但对包内部冗余文件完全无效。关键在于:Composer 默认安装的是 Packagist 上的完整 ZIP 包,不支持“只下某个子目录”。
-
--no-dev只跳过 require-dev 列表,不影响主包内容 -
--optimize-autoloader不删文件,只改 autoloader 逻辑 - 即使设
"minimum-stability": "stable",也改变不了下载包体大小
按需裁剪 vendor 中文语言包的实操路径
目标明确:只保留 zh-CN(或 zh),删掉其他所有 lang/、translations/、locale/ 下的非中文目录。不能靠手动删——下次 composer update 全恢复。必须固化到流程里。
推荐在 composer.json 的 scripts 中加入 post-install-cmd 和 post-update-cmd:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
"scripts": {
"post-install-cmd": [
"@php -r \"array_map('unlink', glob('vendor/**/lang/*[^z][^h]*', GLOB_ONLYDIR));\""
],
"post-update-cmd": [
"@php -r \"array_map('unlink', glob('vendor/**/lang/*[^z][^h]*', GLOB_ONLYDIR));\""
]
}
说明:
- 该命令用 PHP 内置
glob扫描所有vendor/**/lang/下非zh开头的子目录(如en、fr、ja),然后unlink()删除 - 没匹配
zh-CN或zh_TW?加一层宽松匹配:glob('vendor/**/lang/!(zh*)', GLOB_ONLYDIR)(需启用glob的GLOB_BRACE支持,部分系统不兼容) - 更稳妥的做法是用专用工具:
composer require --dev janoside/composer-cleaner,它支持配置白名单(如只留zh、en),且能处理resources/lang、locale等多路径 - 注意:某些包(如
spatie/laravel-translatable)把翻译放在resources/lang/vendor/xxx,这类需额外清理脚本
裁剪后要注意的兼容性陷阱
不是所有包都“安全可删”。有些组件运行时会动态加载语言包,删了会抛 File not found 或静默回退到英文——但你未必立刻发现。
-
symfony/translation依赖symfony/intl的 ICU 数据,删vendor/symfony/intl/Resources/data会导致Locale::getPluralRules()失败 -
laravel-lang/lang是社区维护的多语言包,若你用它做全局翻译,删其他语言前先确认是否真没调用__('message', [], 'fr') -
doctrine/orm的lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php会尝试加载vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php,而后者可能引用vendor/doctrine/annotations/resources——这个目录删不得 - 建议上线前跑一遍
php artisan lang:publish(Laravel)或bin/console translation:extract(Symfony),确认翻译加载无异常
真正要裁的,是那些明确只用于开发或文档展示的静态资源。边界模糊时,宁可多留 2MB,别为省空间引入隐性故障。

















