生产环境必须用 composer install,因为它只还原 composer.lock 锁定的精确版本,跳过解析;而 composer update 会重算依赖树、引入不兼容变更、破坏环境一致性。

composer install 不是“装完就跑”的命令,它只还原 composer.lock 里锁定的依赖版本,跳过版本解析。生产环境必须用它,而不是 composer require 或 composer update。
为什么不能在生产环境跑 composer update
它会重新解析 composer.json 中所有依赖的版本约束,生成新的 composer.lock —— 这意味着:
- 同一份代码,在不同机器上可能装出不同版本的包(比如
monolog/monolog被升到不兼容的 v2.10) - PHP 扩展要求可能悄悄变化(例如某新版本强制要求
ext-intl,而你的服务器没开) - Magento 自身的 DI 编译、代理生成逻辑依赖精确的类签名,版本漂移会导致
bin/magento setup:di:compile失败或运行时报Class not found
composer install --no-dev 的实际作用
它不只是“不装开发依赖”,关键影响有三点:
- 跳过
autoload-dev部分的自动加载规则,减少生产环境的类映射体积 - 不执行
require-dev里的脚本(比如 PHPStan、PHPCS),避免部署卡在静态分析上 - 防止因 dev 包的 autoload 冲突导致
app/code下自定义模块的类被错误覆盖(尤其当第三方模块用了psr-4映射到src/但未隔离时)
执行前必须确认的三件事
漏掉任意一项,composer install 就可能静默失败或留下隐患:
-
composer.lock文件必须存在且和composer.json时间戳一致 —— Git 提交时别忘了它 - PHP CLI 版本必须和 web server 使用的版本一致(常见坑:CLI 是 PHP 8.1,Apache 用的是 8.0,结果
ext-sodium在 CLI 可用,但请求里报错) - 当前用户对
vendor/、generated/、var/目录有写权限 —— Magento 2.4+ 的generated/code默认由 CLI 创建,权限不对会导致后续setup:di:compile报Permission denied
真正麻烦的不是命令本身,而是它依赖的上下文:composer.lock 是否可信、PHP 环境是否统一、文件权限是否继承正确。这些细节不出现在命令行输出里,但决定部署是否真能跑起来。











