FrankenPHP默认不嵌入静态资源,仅打包vendor/下的.php文件;要将public/等静态资源打入二进制,须在Caddyfile中配置file_server { embed public/ },并注意MIME类型、路径大小写及框架内硬编码URL问题。

FrankenPHP 默认不嵌入静态资源,只 embed PHP 文件
FrankenPHP 的 frankenphp build --embed-vendor 只处理 vendor/ 下的 .php 源码文件,不会打包 public/ 里的 CSS、JS、图片等静态资源。它默认仍通过文件系统读取 public/ 目录——也就是说,你生成的二进制运行时,依然依赖外部 public/ 存在且可读。
想把静态资源打进二进制,必须用 Caddy 的 file_server + embed 模式
FrankenPHP 底层是 Caddy,而 Caddy 支持用 file_server 的 embed 指令将静态文件编译进二进制。但 FrankenPHP 并未暴露该能力给高层命令,需手动干预:
- 在项目根目录创建
Caddyfile,显式启用file_server并指定embed -
embed路径必须是相对于 Caddyfile 的相对路径(如embed public/),不能是绝对路径 - 确保
public/下无符号链接或动态生成文件(如mix-manifest.json若含 runtime hash,需提前固化) - 执行
frankenphp build时,Caddy 会自动识别并把embed声明的目录内容静态编译进二进制
示例 Caddyfile 片段:
localhost {
root * public/
php_server
file_server {
embed public/
}
}常见错误:嵌入后 404 或 MIME 类型错乱
嵌入静态资源后,常出现请求返回 404 或浏览器提示“Not Found”,或 JS/CSS 加载失败但状态码是 200 —— 这通常是 MIME 类型未正确识别导致:
立即学习“PHP免费学习笔记(深入)”;
- Caddy 的
file_server默认根据扩展名推断 MIME 类型,但嵌入模式下若文件无扩展名(如public/app)、或扩展名不标准(如.mjs),会 fallback 到text/plain - 解决方法:在
file_server块中显式添加mime指令,例如:mime .mjs application/javascript - 另一个坑是路径大小写敏感:Linux 上
public/Css/app.css和public/css/app.css是不同路径,嵌入后无法跨路径匹配 - 嵌入后
file_server不再支持try_files,所以不要在file_server块里混用try_files,应由php_server处理路由回退
真正“零目录依赖”的二进制,还得清理 public/ 外部引用
即使静态资源已嵌入,Laravel 等框架仍可能在运行时硬编码引用 public/ 下的路径(比如生成 asset URL 时拼接 https://example.com/js/app.js)。这类行为不被嵌入影响,但会导致部署后 URL 错误:
- 检查
APP_URL和MIX_ASSET_URL是否设为相对路径或空值,避免生成绝对域名 - Laravel 中慎用
asset()在服务端渲染时输出完整 URL;改用mix()或前端构建时注入 CDN 域名 - 确认所有
<link>/<script>标签路径不带public/前缀——因为嵌入后,Caddy 已把public/当作 Web 根,路径直接从/开始即可
嵌入静态资源不是简单加个 flag 就完事,它改变了资源加载的生命周期,也放大了路径约定和构建时假设的脆弱性。



















