轻量化 composer 安装需四层收口:命令(--no-dev --optimize-autoloader --prefer-dist)、锁文件(clean composer.lock)、autoload(禁用fallback、清理映射)、包结构(archive excludes);仅靠--no-dev无法清除传递依赖和tests/等目录,必须配合源头排查、配置归档与双内存限制。

轻量化 Composer 安装不是靠删包凑数,而是从安装命令、锁文件、autoload 机制和包内结构四层同时收口;composer install --no-dev --optimize-autoloader --prefer-dist 是底线操作,但仅靠它连一半问题都解决不了。
为什么 composer install --no-dev 后 vendor 还有 phpunit 和 tests/ 目录
因为 --no-dev 只跳过 require-dev 顶层声明的包,不处理它们的传递依赖,也不清理包内部的非代码目录。比如 laravel/framework 在 require 里写了 symfony/var-dumper,而后者又依赖 phpunit/php-code-coverage,这个链路就合法混进来了。
- 查源头:运行
composer why-usage phpunit/phpunit(Composer ≥2.4)或composer depends phpunit/phpunit(旧版),确认是否真被生产代码间接引用 - 删 tests/ docs/ 等目录不能手动
rm -rf vendor/*/tests——有些包(如monolog/monolog)把Handler示例放tests/下且未在 autoload 中声明,删完直接报Class not found - 安全做法是在
composer.json的config块加"archive": {"excludes": ["/tests/", "/docs/", "/examples/", "/.github/"]},再跑composer install --no-dev --prefer-dist,解压时直接跳过
composer install 在 512MB 服务器上 OOM 的真实原因和应对
不是 PHP 配置太小,是 Composer 在 “Resolving dependencies” 阶段把整个依赖图、所有 autoload 映射、lock 元数据全塞进内存,峰值常超 800MB。哪怕设 memory_limit=-1,也会被系统 OOM killer 杀掉。
- 必须组合三参数:
--no-dev(砍掉 dev 包解析)、--optimize-autoloader(生成扁平 classmap,省扫描开销)、--no-plugins(禁用所有第三方插件,避免并发下载竞争) - 内存限制要双保险:
php -d memory_limit=384M COMPOSER_MEMORY_LIMIT=256M composer install --no-dev -o --no-plugins --no-progress——--no-progress不只是隐藏进度条,它关掉了实时计数器和状态快照,减少临时数组分配 - clean install 比增量更省内存:先
rm -rf vendor/,再执行安装;若vendor/已存在且composer.lock有变更,Composer 会启动全量依赖图重建
如何让 composer.lock 真正干净,不再带 dev 包痕迹
--no-dev 参数不会清理 composer.lock 里已存在的 require-dev 记录,部署时可能误判依赖边界。锁文件才是部署事实依据,它脏了,所有优化都白搭。
- 删掉
composer.json中整个"require-dev": { }块(包括花括号),别留空对象 - 运行
composer update --no-dev --lock,不是install——它会重算依赖图并生成不含 dev 元数据的 lock 文件 - 验证:打开
composer.lock,搜索"require-dev"或"phpunit",确认不存在;再检查packages数组长度是否明显减少 - CI 中加校验步骤:
grep -q '"require-dev"' composer.lock && exit 1 || echo "lock clean"
哪些配置项容易被忽略却影响体积和稳定性
最常被忽略的是 vendor/composer/installed.json(几 MB)、vendor/composer/ClassLoader.php 中冗余 autoload 映射,以及某些包自带的 build/、resources/ 目录(比如塞了 Chromium 二进制)。
-
"optimize-autoloader": true必须写入composer.json的config块,否则dump-autoload -o不生效;但注意:如果某包 autoload 同时声明了classmap和psr-4,且classmap包含tests/,优化后仍会加载那些路径 - 用
replace替代虚拟包:如项目已内置 PSR-3 日志实现,就在replace中加"psr/log": "3.0.0",Composer 就不会下载官方空壳包 - 避免
autoload.files混用:全局files会每次请求都 require,若指向大文件或未压缩的工具类,启动变慢且无法被 classmap 优化











