上线部署应加 --no-dev 参数并优化 autoload;清理 require-dev 中非必要包;替换冗余虚拟包;删除 vendor/bin 冗余脚本;避免 autoload 混用 classmap/psr-4 引入未用目录。

composer install 时哪些包其实根本用不到
很多项目 vendor 膨胀,不是因为业务依赖多,而是 dev-dependencies 被装进了生产环境,或者间接拉入了大量未使用的工具类包(比如 phpunit、symfony/var-dumper、laravel/pint 这类开发期才需要的包,在线上完全不跑)。
实操建议:
- 上线部署必须加
--no-dev参数:composer install --no-dev --optimize-autoloader - 检查
composer.json的require-dev区块,把只用于本地调试、CI 或代码风格检查的包全挪进去 - 运行
composer show --dev确认当前已安装的 dev 包有哪些,对照项目实际运行链路,看有没有“悄悄混进来”的
autoload 里 classmap 和 psr-4 混用导致 vendor 膨胀
有些包在 composer.json 中同时声明了 classmap 和 psr-4 自动加载规则,尤其是老版本 Laravel 扩展或自研私有包,会把整个 src/ + tests/ + examples/ 全扫进 autoloader 映射,哪怕你只用了其中 1 个类。
实操建议:
- 用
composer dump-autoload -o(即--optimize)能合并映射为静态数组,跳过文件扫描,但前提是包本身 autoload 配置干净 - 若发现某包的
autoload.classmap包含tests/或docs/目录,优先考虑 fork 后删掉再发布私有版,或提 PR 去上游修复 - 运行
composer show vendor/package-name查它的 autoload 定义,比直接翻源码快
使用 replace 和 provide 替代真实依赖来砍掉冗余包
某些包只是提供接口或空实现(比如 psr/log、psr/container),而你的框架或基础组件已经内置了兼容实现,这时 Composer 仍会下载一个空壳包 —— 表面看体积小,实则增加 autoloader 条目和解析开销。
实操建议:
- 在根
composer.json的replace字段中声明已兼容的虚拟包:"psr/log": "3.0.0",Composer 就不会再去装psr/log的官方实现 - 慎用
provide:它只告诉 Composer “我提供了这个能力”,但不阻止别人 require,真正想彻底排除,得用replace+"conflict"组合 - 执行
composer update后,用composer show psr/log验证是否真的没装上
vendor/bin 下的可执行文件占空间却不常被调用
vendor/bin 里一堆脚本(如 phpunit、phpcs、phinx)每个都带自己的依赖树,虽然不进 autoloader,但解压后可能占几 MB。尤其在容器镜像或 serverless 环境中,这些二进制文件纯属冗余。
实操建议:
- 部署后手动删掉:
rm -rf vendor/bin/*(前提是确认没通过 shell 调用它们) - 更稳妥的做法是用
composer config bin-dir false关闭 bin 目录生成,再把必要命令改用vendor/autoload.php+exec('php vendor/some/package/bin/script')方式调用 - 注意:Laravel 的
artisan不受影响,它不在vendor/bin下;但phpunit若被composer require --dev phpunit/phpunit安装,则默认会软链进vendor/bin
真正难压缩的是那些既没被 --no-dev 过滤、又没被 replace 掉、还自带庞大 autoload 映射的“中间层”包 —— 比如某些 SDK 把 HTTP 客户端、重试逻辑、日志、配置全打在一个包里。这时候光靠 Composer 参数没用,得拆包或换实现。










