生产环境必须在构建阶段完成依赖安装与优化,禁止现场执行 composer install;需使用 --no-dev --optimize-autoloader --classmap-authoritative --no-interaction 五个参数闭环组合,并清理 vendor/bin、tests、docs 等敏感冗余文件,同时启用 opcache.enable_cli=1。

生产环境不能靠 composer install 现场安装,必须在构建阶段完成依赖解析、类映射生成和冗余清理——否则部署就是把权限问题、版本漂移和源码泄露一起推上线。
为什么不能在生产机上跑 composer install
这不是性能问题,是安全与稳定底线:
-
file_put_contents(./composer.json): failed to open stream: Permission denied—— 部署用户通常没权限写vendor/或修改composer.lock,报错后排查路径、权限、SELinux 耗时远超预估 - 本地 PHP 8.2,线上是 8.1?
Your platform does not meet the requirements直接中断部署,CI 流水线卡死 -
composer.json或.env被 Nginx 错误配置暴露,几秒内数据库密码、API 密钥进攻击者手里 - 开发机装了
phpunit,但没删vendor/bin/phpunit,一旦 web 目录可执行或存在路径遍历漏洞,就等于白送攻击入口
composer install --no-dev --optimize-autoloader --classmap-authoritative --no-interaction 必须一起用
这五个参数不是“可选组合”,而是互锁生效的硬性闭环:
-
--no-dev:跳过require-dev所有包(phpunit、symfony/debug-bundle),否则它们会混进 autoload,拖慢加载 + 暴露调试入口 -
--optimize-autoloader:生成vendor/composer/autoload_classmap.php,把类名直连文件路径,单次类加载从平均 1.2ms 降到 0.05ms;不加它,高并发下 autoload 就是 I/O 瓶颈 -
--classmap-authoritative:强制 autoloader 只查 classmap,不 fallback 到文件扫描——这才是真正绕过stat()的关键;漏掉它,--optimize-autoloader几乎无效 -
--no-interaction:防止遇到 GitHub credentials 提示卡住 CI,尤其 Docker 构建时直接超时失败
少一个参数,就可能让服务响应变慢、偶发 500 或自动化挂起。
装完还得删:vendor/ 里哪些东西必须手动清理
composer install --no-dev --optimize-autoloader 是底线,但光靠它远远不够。真正该删的是这些:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
vendor/bin/—— 全部删除(除非你明确需要某个二进制如phinx在线上运行) -
vendor/**/tests/、vendor/**/Tests/、vendor/**/test/、vendor/**/Test/ vendor/**/{.git,.gitignore,.travis.yml,phpunit.xml,phpstan.neon,psalm.xml}-
vendor/**/docs/、vendor/**/examples/、vendor/**/demo/ -
vendor/composer/installed.json—— 含完整包版本与哈希,泄露可辅助攻击者判断组件漏洞
Linux/macOS 下推荐显式清理:rm -rf vendor/bin vendor/*/tests vendor/*/Tests vendor/*/test vendor/*/Test vendor/*/docs vendor/*/examples vendor/*/demo vendor/*/demo vendor/composer/installed.json;避免用模糊 find,防止漏删。
验证是否真生效,别只看命令有没有报错
执行完部署命令后,立刻检查两件事:
- 打开
vendor/composer/autoload_real.php,搜索findFile方法:如果只剩if ($classMap = $this->classMap)分支,且完全删掉了foreach ($this->prefixesPsr4相关逻辑,才算真正“权威” - 用
strace -e trace=stat,openat php -r "new AppModelsPost();"观察是否还有大量stat("/path/to/src/Models/Post.php")失败调用;没有,说明 fallback 已关闭
最容易被忽略的是 opcache 配置:opcache.enable_cli=1 必须开,否则 autoload_classmap.php 每次请求都得重新解析,反而比不优化更慢。










