根本原因是composer默认每次install都重新解析并激活所有插件,触发远程请求或文件扫描等耗时操作;建议用composer_no_plugins=1跳过加载、精简require-dev中的非必要插件、升级至composer 2.2+移除已原生替代的插件。

为什么 composer install 加载插件特别慢?
根本原因不是插件本身,而是 Composer 默认在每次安装时都重新解析所有插件的依赖、执行 PluginManager::load() 并触发其 activate() 方法——哪怕插件没变。更糟的是,某些插件(比如 hirak/prestissimo 旧版、dealerdirect/phpcodesniffer-composer-installer)会在激活阶段执行远程请求或文件扫描,直接拖慢整个流程。
实操建议:
- 运行
composer install -v观察日志,定位耗时插件(注意输出中类似Loading plugin ...的行) - 检查
composer.json中require-dev是否混入了仅用于 CI 的插件(如phpstan/extension-installer),它们在本地开发时完全没必要加载 - 确认插件是否真需要全局启用:很多插件(如
symfony/flex)其实只在create-project或首次安装时起作用,后续可安全移除
用 COMPOSER_NO_PLUGINS=1 跳过插件加载
这是最直接有效的提速手段,尤其适合 CI 环境或仅需生成 vendor/autoload.php 的场景。它不卸载插件,只是跳过 PluginManager 的初始化逻辑,对依赖解析和自动加载无影响。
实操建议:
- CI 中优先使用:
COMPOSER_NO_PLUGINS=1 composer install --no-dev --optimize-autoloader - 本地调试时临时禁用:如果怀疑某插件导致
composer dump-autoload卡住,加这个环境变量再试一次 - 注意副作用:部分插件提供命令(如
phpstan的composer phpstan)会失效;但只要不调用这些命令,不影响项目运行
composer install 和 composer update 对插件行为不同
install 读取 composer.lock,复用已解析的依赖图,插件加载集中在 PluginManager::load() 阶段;而 update 会重新走完整依赖求解流程,插件可能被多次实例化(例如 composer/installers 在处理每个包时都可能触发),耗时明显更高。
实操建议:
- 日常开发尽量用
composer install,而非频繁composer update - 若必须
update,先用composer update --dry-run确认是否真有变更,避免无意义重算 - 某些插件(如
ocramius/package-versions)在update时会重写composer.lock元数据,加剧延迟——这类插件建议仅在发布前启用
替换或精简高开销插件
不是所有插件都值得保留。比如 hirak/prestissimo 已被 Composer 2.0+ 原生并行下载替代;roave/security-advisories 虽有用,但每次 update 都要拉取全量 CVE 数据,本地开发时完全可以移出 require-dev。
实操建议:
- 升级到 Composer 2.2+ 后,删掉
hirak/prestissimo——它不仅无效,还可能干扰原生下载器 - 把
phpstan/extension-installer移到require下(而非require-dev),避免每次install都加载却不用 - 用
composer show --plugins列出当前激活插件,逐个评估:这个插件解决的问题,是否还能用其他方式(如脚本、GitHub Action)替代?
插件加载慢的本质是「不该运行的代码被执行了」。优化的关键不是加速插件本身,而是让它们在不需要的时候彻底不出现。这点在团队协作中容易被忽略——一个人加的插件,所有人跟着一起等。











