上线前必须加 --optimize-autoloader(或 -o),并搭配 --classmap-authoritative,否则 psr-4 动态映射导致每次类加载都扫描目录;该选项仅优化类加载,不影响 require_once。

composer install 时怎么启用 optimize-autoloader
上线前必须加 --optimize-autoloader(或简写 -o),否则 Composer 会走慢速的 PSR-4 动态路径映射,每次 class_exists() 或 new 一个类都要扫描目录。
实操建议:
- 线上部署一律用
composer install --no-dev --optimize-autoloader --classmap-authoritative - 本地开发不用加,加了反而让 class 修改后不自动重载(比如改了类名但没删 vendor/composer/autoload_classmap.php)
-
--classmap-authoritative是关键搭档:它告诉 Autoloader “只信 classmap,别去文件系统里猜”,能彻底跳过file_exists()检查,性能提升明显
为什么 vendor/autoload.php 在生产环境仍可能慢
即使开了 --optimize-autoloader,如果项目里有大量未被扫描到的类(比如运行时拼接类名、__autoload 遗留逻辑、或用了 class_alias()),Autoloader 还是会 fallback 到慢路径。
常见错误现象:
- APCu 缓存没开,
vendor/autoload.php每次请求都重新 require 数十个文件 - 用了
psr-0或混用多种 autoload 类型,composer dump-autoload后 classmap 不完整 - 某些包在
autoload-dev里注册了测试用的类,但--no-dev没生效,导致 classmap 错乱
检查方法:临时加一行 var_dump(\Composer\Autoload\ClassLoader::getStaticMap()); 看是否包含你常用的类;空数组或 key 极少,说明 classmap 没打全。
optimize-autoloader 对 require_once 的影响
这个选项**只优化 class 加载,不影响 require/require_once 行为**。很多人误以为开了它就能加速所有文件加载,其实不是。
使用场景:
- 框架中大量
new Router()、app()->make(Handler::class)这类依赖反射或字符串类名的调用 - CLI 命令反复执行(如队列 worker),每轮都要加载几十个命令类
- 微服务里高频 HTTP 请求触发大量新实例化
注意:如果你代码里满屏 require_once 'xxx.php',优化 autoloader 完全没用——得靠 OPCache 或 APCu 缓存 realpath 结果。
CI/CD 流程里容易漏掉的三个点
自动化部署时,--optimize-autoloader 很容易被覆盖或忽略,尤其在多阶段构建中。
- Docker 构建时用了
composer install但没传参数,镜像里还是开发模式 autoload - CI 脚本里写了
composer install --no-dev,却忘了加-o,上线后 QPS 掉 20% 才发现 - 有些团队用
composer dump-autoload --optimize单独执行,但没配--classmap-authoritative,classmap 生成了,fallback 还开着
最稳做法:把完整命令写死在部署脚本里,不要依赖 .composer/config.json 的全局设置——不同环境配置容易冲突。
classmap 文件一旦生成,就和源码结构强绑定;删了一个类文件,不重新 dump,autoload_classmap.php 里还留着旧路径,报错信息会指向不存在的文件行号。这点比想象中更隐蔽。











