frankenphp二进制默认不打包composer依赖,需显式使用--embed-vendor参数才能将vendor中php文件静态嵌入,并重写autoloader路径;但ext扩展仍需宿主机提供,且要求vendor已完整安装、无动态路径引用。

Composer 依赖默认不会打进 FrankenPHP 二进制
FrankenPHP 的 frankenphp build 命令打包的是 PHP 应用的「运行时快照」,它只 embed 当前目录下 vendor/ 的 PHP 文件(即已安装的 Composer 包源码),但不会自动把 Composer 的 autoloader、类映射或扩展依赖(如 ext-curl)编译进二进制。你看到的「二进制能跑」,其实是靠运行时动态加载 vendor 目录 —— 这和「打进二进制」有本质区别。
真正打进二进制:必须用 frankenphp build --embed-vendor
这个 flag 会把 vendor/ 下所有 .php 文件(不含扩展、不含二进制资源)静态 embed 到最终二进制中,并重写 autoloader 路径。但它有几个硬性前提:
-
vendor/必须已存在且完整(composer install --no-dev最好) - 不能有依赖通过
include/require动态加载未声明的 PHP 文件(比如某些插件扫描目录) - 所有包必须是纯 PHP;含
ext-*依赖的包(如ext-gd)仍需宿主机提供对应扩展,FrankenPHP 不打包扩展本身 - 如果你用了
composer install --classmap-authoritative,embed 后 autoloader 性能更好,推荐加上
示例命令:
frankenphp build --embed-vendor --output myapp ./public/index.php
常见失败现象:autoloader 找不到类 or Class not found
这不是 FrankenPHP bug,而是 embed 过程没覆盖到实际加载路径。典型原因:
-
vendor/autoload.php被其他脚本二次 require(比如你手动require 'vendor/autoload.php'在入口外),导致 embed 后路径错乱 - 某个包在
autoload.files里注册了绝对路径文件(如/tmp/foo.php),embed 时被跳过 - 使用了
psr-4映射但命名空间与目录结构不严格匹配,embed 后 classmap 生成失败 -
composer.json里有"optimize-autoloader": true,但构建前没跑composer dump-autoload --optimize,embed 时 fallback 到慢速 autoload
嵌入后体积大、启动慢?注意 vendor 冗余
--embed-vendor 是字面意义的「复制所有 .php 文件进二进制」,vendor 里哪怕一个测试工具(如 phpunit/phpunit)也会被打进去。生产构建前务必:
- 用
composer install --no-dev --no-scripts清掉开发依赖 - 检查
vendor/bin/是否被意外引用(有些框架会 require 它下面的脚本) - 避免在
autoload.files里 include 大型配置文件(如 YAML/JSON 解析器加载的 schema 文件) - 如果用了 Laravel,确认
bootstrap/cache/packages.php和bootstrap/cache/config.php已生成,否则 embed 时会漏掉优化后的配置缓存
embed 后二进制通常比不 embed 大 5–15 MB,但冷启动快 200–400ms(实测 Laravel 9 + 32 个包)。
真正难处理的是那些靠 file_get_contents(__DIR__.'/../vendor/xxx') 硬编码读取非 PHP 资源的包 —— FrankenPHP 不处理这类路径,得手动改源码或用 frankenphp embed 配合自定义资源注册。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











