部署 Laravel 项目必须用 composer install --no-dev,误用 composer update 会忽略 composer.lock 导致版本漂移和 BC Break;composer.lock 必须提交 Git,require/require-dev 需严格区分,版本约束(如 ^)须谨慎使用。

部署 Laravel 项目时,依赖管理出错不是“可能崩溃”,而是“大概率立刻崩溃”。真正的问题往往不出在命令会不会敲,而在于对 composer.json 的约束写法、composer.lock 的角色认知,以及开发与生产环境的操作逻辑是否清晰。
崩溃最常见原因:误用 composer update 替代 composer install
上线或 CI/CD 流水线中执行 composer update,等于主动放弃版本控制。它会忽略 composer.lock,重新解析所有依赖,可能装上带 BC Break 的小版本(比如某包从 3.2.7 升到 3.3.0,方法签名已变),或跨主版本升级(如 "laravel/framework": "^10.0" 在本地锁着 9.52.0 时被手动改写,update 就会强制拉 10.x 并报 Class not found)。
- 生产环境、Git 拉取新项目、CI 构建脚本——一律用
composer install --no-dev -
composer update只应在开发阶段明确要升级某个包时使用,且必须配合git status确认无未提交改动 - 升级后,
composer.lock必须立即提交到 Git,否则别人install就是旧版本
版本约束写错:一个 ^ 就能毁掉整个上线
^10.0 不代表“安全小升级”,它代表“允许升到 10.999.999,但禁止到 11.0.0”;可如果你当前是 Laravel 9,又把 require 改成 ^10.0,composer update 就会强行跨主版本——而 Laravel 10 要求 PHP 8.1+、废弃了大量 Facade、重写了队列驱动逻辑,代码不改就崩。
- 主版本升级前,必须先看官方 Upgrade Guide,逐项检查废弃类、配置变更、PHP 版本门槛
- 核心包如
laravel/framework、guzzlehttp/guzzle建议用固定版本(如"7.8.1")或~10.3.0(只允许补丁级更新) - 加新包时别直接
composer require xxx,先用--no-update写入composer.json,再手动收紧版本号,最后composer update xxx
composer.lock 被忽略或损坏:一致性保障彻底失效
composer.lock 不是可选文件,它是项目依赖的“法律合同”。只要它没进 Git、被 .gitignore 拦截、或内容损坏(空文件、JSON 格式错误、sha256 字段错位),不同机器安装出来的 vendor 就一定不一致——轻则行为差异,重则 Class not found 或 Call to undefined method。
- 新建项目后,第一次
composer install完成,立刻git add composer.lock - 怀疑 lock 损坏?运行
composer validate,它秒级告诉你哪个文件非法 - lock 文件损坏但 Git 历史还在?用
git checkout HEAD -- composer.lock恢复 - lock 文件丢失且无 Git?删掉
vendor和composer.lock,再composer install——但这只是临时救急,新生成的 lock 已和原环境不一致
require 与 require-dev 划分混乱:生产环境多装几十 MB 无用代码
把 phpunit/phpunit、laravel/pint、symfony/var-dumper 放进 require,会导致线上部署白装一堆测试和调试工具,不仅增大体积,还可能因自动注册服务提供者引发冲突;反过来,漏掉 doctrine/dbal(迁移必需)进 require,上线后 php artisan migrate 直接报错。
- 运行时真正需要的库进
require;仅用于开发、测试、构建的进require-dev - 线上部署永远加
--no-dev,但部署前务必验证功能完整(比如日志是否仍能写入、队列是否可分发) - 像
roave/security-advisories这种纯校验型包,必须放require-dev,它不提供运行时代码,只做安装拦截











