生产环境必须用 composer install,它读取 composer.lock 确保依赖版本完全一致;混用 composer update 会绕过 lock 文件引发线上崩溃。

composer install 和 composer update 不能混用
生产环境必须用 composer install,不是“推荐”,是硬性要求。它读取 composer.lock 中锁定的精确版本号,确保每次部署的依赖树完全一致。一旦换成 composer update,哪怕加了 --no-dev,也会重新解析 composer.json、忽略 lock 文件、拉取未验证过的新版本——线上崩溃往往就发生在 monolog/monolog 从 3.5.0 升到 3.6.0 的那一秒。
常见误操作:
- CI 脚本里写
make deploy,背后却调用了composer update --no-dev - 手动修复线上问题时,在服务器上直接跑
composer update,结果引入不兼容变更 -
composer.lock没提交进 Git,composer install自动退化为update行为
--no-dev 不是开关,是约束条件
--no-dev 只在 composer.lock 文件本身不含 dev 包时才真正生效。如果 lock 文件里已经记录了 phpunit/phpunit 或 symfony/debug-bundle,那执行 composer install --no-dev 会直接报错 dev dependencies not found,而不是“跳过安装”。
所以真正要管的不是命令,而是 lock 文件的生成方式:
- 首次上线前,必须在干净环境(无
vendor/、无composer.lock)运行:composer update --no-dev --lock - CI 脚本中应前置清理:
git clean -xffd vendor/ && rm -f composer.lock,再拉取最新合规 lock - 部署后验证:
composer show --dev应提示 “No dependencies installed for development”
--optimize-autoloader 不是可选优化,是性能底线
不加 --optimize-autoloader(或简写 -o),autoload 就靠运行时遍历目录匹配类名,单次加载耗时约 1.2ms;加上后生成 vendor/composer/autoload_classmap.php,直连类名与文件路径,降到 0.05ms 左右。高并发下,这点差异就是 I/O 瓶颈和响应毛刺的分界线。
注意它和 --classmap-authoritative 的关系:
-
--optimize-autoloader是基础项,必须加 -
--classmap-authoritative是增强项,告诉 autoloader “类只可能在 classmap 里,别再去 PSR-4/PSR-0 目录找”,能进一步提速,但要求所有类都已映射(比如不能有动态 require 的测试类) -
--optimize已废弃,别用
部署脚本里漏掉 --no-interaction 就可能卡死
--no-interaction(或简写 -n)防止 Composer 在构建过程中弹出交互提示。典型场景包括:
- Docker 构建时遇到
Do you trust this repository?,超时失败 - CI 流水线里碰到 GitHub Token 提示,整个 job 挂起
- Nginx 部署后访问首页返回 502,查日志发现 PHP-FPM worker 卡在等待用户输入
它和 --no-dev、--optimize-autoloader 是互锁生效的最小安全集,少一个都可能让部署“看起来成功,实际不可用”。
真正容易被忽略的是:这些参数必须组合使用,且清理动作(如 rm -rf vendor/)得放在命令之前——缓存复用、残留文件、lock 文件污染,三者任意一个没控住,--no-dev 就只是个心理安慰。


















