--no-dev是生产部署强制参数,必须加;不加会导致phpunit等dev包装入vendor,引发体积膨胀、autoload冲突及运行时错误,且仅当composer.lock不含dev记录时才真正生效。

为什么 --no-dev 不是可选而是必须加
不加 --no-dev,生产环境会把 phpunit、phpstan、roave/security-advisories 这类包一起装进 vendor/,体积多出 30%~70%,还可能触发运行时错误——比如 Class 'PhpCsFixer\Finder' not found 这种报错,你根本没写相关代码,只是因为 friendsofphp/php-cs-fixer 被误加载进 autoloader。
它不只是“少装几个包”,而是直接跳过 require-dev 声明的所有顶层包、不注册 autoload-dev 路径、不执行 post-autoload-dump 等 dev-only 钩子。但注意:--no-dev 不会剔除这些包的传递依赖——如果 monolog 也依赖 sebastian/exporter,那它仍会保留。
- 必须确保
composer.lock已存在且稳定;否则composer install --no-dev会退化为composer update --no-dev,重新解析依赖,反而更慢、更不可控 -
require-dev里不能混入运行时必需的包(比如旧版symfony/debug或某些 SDK 的调试驱动) - 检查是否在代码里手动
require了tests/或src/DevTools/下的文件,这类路径若在autoload-dev里,加了--no-dev就直接报错
--optimize-autoloader 到底优化了什么
它不是“让自动加载变快一点”,而是彻底绕过 PSR-4 的目录扫描逻辑:把所有类路径预编译成一个扁平数组,存进 vendor/composer/autoload_classmap.php。单次类加载耗时从 0.8–2.1ms 降到 0.03–0.07ms,高并发下效果极明显。
这个优化只对 PSR-0/PSR-4 有效,不影响 files 类型自动加载。启用后,class_exists('Foo\Bar') 不再遍历 src/、lib/ 目录,而是查表返回路径。
- 必须配合
--no-dev使用,否则 classmap 里会混入测试类,白白膨胀文件 - 验证是否生效:删掉某个类文件后执行
class_exists(),如果立刻报Class not found而不是静默失败或 fallback 查找,说明 classmap 已接管 - 生成的
autoload_classmap.php大小应比开发环境小 30% 以上;差得不多,说明autoload-dev路径泄露进了主 autoload 块
--classmap-authoritative 是加速还是断电
它是“断电式加载”:告诉 autoloader “classmap 里没有的类就一定不存在”,彻底关闭文件系统扫描。不是提速开关,而是加载策略切换——一旦开了,找不到类就立刻报错,不再尝试 PSR-4 fallback。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
这能进一步压低类加载开销,但代价是零容忍。很多项目踩坑是因为:某处用了 class_exists('SomeOptionalFeature') 做运行时探测,而这个类只在 dev 包里定义,--classmap-authoritative 一开,探测直接失败,功能逻辑中断。
- 仅推荐在 Laravel 8+、Symfony 5.3+ 等已默认启用该模式的框架中使用
- 上线前务必检查所有
class_exists()、interface_exists()调用,确认被探测的类属于生产必需范围 - CI 流程中应加入验证脚本:运行
php -d opcache.enable=1 -d opcache.enable_cli=1 vendor/autoload.php,确认无 fatal error
Docker 和 CI 中怎么固化 --no-dev 行为
在 Dockerfile 里写 RUN composer install --no-dev --optimize-autoloader --classmap-authoritative --no-interaction 是基础操作,但容易忽略三点:lock 文件来源、构建机环境一致性、以及 --no-scripts 的必要性。
--no-interaction 必须带上,否则 CI 可能卡在 yes/no 提示上;--no-scripts 则用于屏蔽 post-install-cmd 里那些只适合开发的命令(比如生成测试覆盖率报告、清理缓存等),避免它们在线上意外执行。
- Docker 构建前,确保
composer.lock已由 CI 生成并提交,不要靠构建时composer update动态生成 - CI 机器上应禁用 xdebug 等开发扩展,或通过
"config": {"platform": {"ext-xdebug": "3.0.0"}}在composer.json中锁定平台,防止因本地扩展差异导致依赖解析不一致 - 镜像构建完成后,建议用
du -sh vendor/对比体积,并检查vendor/composer/autoload_classmap.php是否不含tests/或dev/路径
真正难的不是记住这几个参数,而是厘清哪些包本不该出现在 require-dev 里——比如某个日志驱动的调试适配器被放错了位置,线上切日志时就突然失效。这种问题不会报错,只会行为异常,排查起来最耗时间。

















