必须在生产环境部署、CI/CD构建、离线安装三类场景下加--no-scripts,以防止因缺失Node.js、PHP扩展或敏感操作等导致的post-install-cmd等脚本执行失败。

什么时候必须加 --no-scripts
生产环境部署、CI/CD 构建、离线安装这三类场景下,--no-scripts 不是“可选优化”,而是防止失败的必要参数。
常见触发失败的原因包括:项目依赖前端构建(如 npm run build),但 CI 容器没装 Node.js;或脚本里调用了本地开发工具(如 php artisan optimize),而线上环境未装 Laravel 扩展;又或者某个包的 post-install-cmd 尝试写入 .env 或生成密钥,直接暴露敏感信息。
- 生产机通常不装 git / npm / node / zip 扩展,
post-install-cmd一执行就报sh: git: not found或Command "npm" is not executable - CI 流水线拉取的是未经签名的分支或 fork 仓库,脚本可能含恶意逻辑(RCE 风险)
- Docker 构建中若同时用
--no-scripts和--no-autoloader,会导致Class not found—— 因为 autoload 文件根本没生成
哪些脚本会被 --no-scripts 跳过
--no-scripts 会跳过 composer.json 的 scripts 字段里定义的所有钩子,不管类型、时机或是否带 @ 前缀。
典型被跳过的有:post-install-cmd、pre-autoload-dump、post-update-cmd、pre-package-install,以及任意自定义命名的脚本(比如 build-assets)。
- 它不影响插件(plugin)行为,例如
composer/installers或phpstan/extension-installer仍会照常运行 - 它不阻止
vendor/autoload.php生成——这是 Composer 核心流程,和脚本无关 - 像 Laravel 的
php artisan config:clear这类命令,如果写在post-install-cmd里,就会被跳过;但如果你手动再跑一遍,不受影响
--no-scripts 和 --no-autoloader 别混用
这两个参数作用完全不同,混用是线上事故高频原因。
--no-scripts 只关脚本;--no-autoloader 是彻底跳过 vendor/autoload.php 和所有 classmap 生成。后者一旦启用,除非你手动维护 autoload,否则任何 new 或 use 都会直接报错。
- CI 构建中误加
--no-autoloader,后续phpunit或php -l检查全挂 - 离线安装时,
--no-autoloader是临时手段,但必须紧接着补composer dump-autoload -o,否则运行时找不到类 -
--no-scripts在composer create-project中也生效,但某些骨架项目(如 Symfony skeleton)靠脚本完成初始化,跳过会导致项目不完整
为什么不能靠环境变量替代 --no-scripts
Composer 不识别 COMPOSER_NO_SCRIPTS=1 这类环境变量,必须显式传参。
有人试图在 Dockerfile 里写 ENV COMPOSER_NO_SCRIPTS=1,结果脚本照常执行——因为该变量压根不被解析。唯一可靠方式就是每个命令都带上 --no-scripts。
- 在
composer require、composer update、composer install中都有效 - 它不会影响
composer run-script的手动调用——那个是显式触发,不在禁用范围内 - 某些私有包文档里写的“请运行
composer install初始化”,实际指的是先--no-scripts装依赖,再手动composer run-script post-install-cmd,这点容易被忽略
真正关键的不是“要不要加”,而是“加在哪一步”。很多团队在 Docker 构建里只给 install 加了 --no-scripts,却在后续 RUN composer run-script post-install-cmd 里忘了检查该脚本是否依赖其他未装工具——这时候失败就不再是 Composer 的问题,而是执行路径没对齐。











