使用 FrankenPHP 部署 WordPress:从零安装、生产级 Caddyfile 到热重载完整指南
【免费下载链接】frankenphp🧟 The modern PHP app server项目地址: https://gitcode.com/GitHub_Trending/fr/frankenphp
本文以 FrankenPHP 官方文档(docs/es/wordpress.md,英文版见 docs/wordpress.md)为主体,系统讲解如何在 WordPress 站点上启用 FrankenPHP:先用php-server命令完成最小安装,再通过Caddyfile搭建生产级配置(自动 HTTPS、HTTP/3、Zstandard/Brotli/Gzip 压缩),最后结合内置 Mercure 中心为 WordPress 主题接入热重载(hot reload)开发工作流。读完本文,你将掌握一套可直接落地的 WordPress + FrankenPHP 部署与开发方案。
为什么用 FrankenPHP 运行 WordPress
FrankenPHP 是一个基于 Caddy 构建的现代 PHP 应用服务器,PHP 解释器直接内嵌于进程之中,无需单独的 PHP-FPM 进程。将 WordPress 跑在 FrankenPHP 上可以获得一套现代、高性能的栈:自动 HTTPS 证书签发与续期、HTTP/3 支持、Zstandard(zstd)压缩等,均由 Caddy 与 FrankenPHP 原生产出。此外,FrankenPHP 内置的 Mercure 中心与 hot reload 功能,能让 WordPress 主题开发做到"改完即刷新",大幅提升开发体验。
WordPress 最小安装:一条命令跑起来
官方文档给出的最小安装路径极其简单,只需 5 步:
从 WordPress 官网下载 WordPress 安装包;
解压 ZIP 压缩包,并在解压出的目录中打开终端;
执行启动命令:
frankenphp php-server浏览器访问
http://localhost/wp-admin/,按提示完成 WordPress 安装向导;完成。
php-server是 FrankenPHP 提供的一个"开箱即用的生产级 PHP 服务器"子命令,其实现位于 caddy/php-server.go。从源码看(cmdPHPServer函数),该命令在底层做了这些事:默认监听:80端口、将.php作为脚本扩展名、自动生成try_files回退规则(优先匹配现有文件,其次index.php,最终回落到文件服务器),并在启动时默认启用 zstd、br、gzip 三层压缩编码。也就是说,这一条命令已经自带压缩、静态文件服务与 PHP 执行能力,适合快速演示与开发。
php-server还支持若干有用参数(均见 caddy/php-server.go 的 flag 定义):
| 参数 | 简写 | 作用 |
|---|---|---|
--domain | -d | 指定域名,启用 HTTPS 并切换到 443 端口 |
--root | -r | 指定站点根目录 |
--listen | -l | 自定义监听地址 |
--worker | -w | 指定 worker 脚本(可重复) |
--watch | 无 | 监视文件变化(常与 hot reload 搭配) |
--access-log | -a | 启用访问日志 |
--debug | -v | 输出详细调试日志 |
--mercure | -m | 启用内置 Mercure 中心 |
--no-compress | 无 | 关闭 zstd、br、gzip 压缩 |
例如本地用 HTTPS 域名方式启动:frankenphp php-server --domain=example.com,此时默认监听端口会切换到 443 并使用 HTTPS(源码中通过certmagic.HTTPSPort实现)。
生产级配置:用frankenphp run配合 Caddyfile
最小安装适合演示,若要用于生产,官方文档推荐使用frankenphp run配合一个Caddyfile。以下配置来自 docs/es/wordpress.md(与英文版 docs/wordpress.md 一致):
example.com php_server encode zstd br gzip log逐行拆解:
example.com:站点地址。FrankenPHP 会为该域名自动签发并维护 HTTPS 证书(同时监听 443 端口支持 HTTP/3),只要域名的 A/AAAA 记录指向服务器即可;php_server:Caddy 指令,作用等价于"先尝试匹配 PHP 文件,其余交给静态文件服务",是大多数应用的最佳选择(若需要完全掌控可改用底层php指令,详见 docs/config.md 的php_server/php指令说明);encode zstd br gzip:开启响应压缩,编码优先级为 Zstandard → Brotli → Gzip,浏览器支持哪种就协商哪种;log:开启访问日志,便于生产排障。
php_server指令的常用子选项
php_server是 Caddyfile 站点块中的高级指令,支持多种子选项(完整列表见 docs/config.md)。与 WordPress 部署最相关的几个:
example.com root public/ # 显式指定站点根目录(WordPress 推荐将根目录指到 wp 源码目录) php_server { root public/ # 与上方等价,可写在这里 env WP_ENV production # 为 PHP 注入环境变量 request_body_timeout 60s # 请求体读超时,默认 60s,0 表示禁用 # worker { # worker 模式按需开启,见下文 # file index.php # } }注意:FrankenPHP 默认会为所有主机名(包括localhost)自动启用 HTTPS。如果开发环境想关闭,可在启动时设置SERVER_NAME环境变量为http://或:80(详见 docs/config.md 的"Disabling HTTPS"一节)。此外,官方仓库还提供了一个带注释的完整 Caddyfile 模板(caddy/frankenphp/Caddyfile),其中包含了 Mercure 的注释配置与SERVER_NAME、SERVER_ROOT、FRANKENPHP_CONFIG等便捷环境变量,可直接作为生产起点。
进阶:WordPress 与 worker 模式
若你的 WordPress 站点启用了任意插件或自定义代码把 PHP 常驻内存(worker 模式),请阅读 docs/worker.md。worker 模式让应用只启动一次,之后请求处理只需数毫秒,但代价是代码改动不会即时生效——这正是下文 hot reload 要解决的核心痛点之一。
为 WordPress 启用热重载(Hot Reload)
Hot reload 是 FrankenPHP 面向开发环境的招牌功能:当工作目录中的 PHP、模板、JS、CSS 等文件发生变化时,浏览器无需手动刷新即可实时更新页面,工作流类似前端工具链中的 HMR(Hot Module Replacement)。官方明确指出该功能"原生兼容 WordPress、Laravel、Symfony 以及任何其他 PHP 应用或框架"(见 docs/hot-reload.md)。
其工作链路如下(详见 docs/hot-reload.md 的"How FrankenPHP hot reload works"一节):
- FrankenPHP 底层基于
e-dant/watcher库监视文件系统变化(caddy/hotreload.go中定义了默认监视模式); - 文件变化时,将变更文件列表封装为 JSON 推送到内置的 Mercure 中心;
- 浏览器端的 JS 库订阅 Mercure 事件;
- 若页面加载了 Idiomorph 库,则对 DOM 进行 morph(保留滚动位置与输入状态);否则执行整页刷新。
第一步:在 Caddyfile 中开启 Mercure 与 hot_reload
热重载依赖内置的 Mercure 中心来推送事件,因此在 Caddyfile 中需要同时启用 Mercure 与hot_reload子指令(配置示例来自 docs/es/wordpress.md):
localhost mercure { anonymous } php_server { hot_reload }mercure { anonymous }:启用内置 Mercure 中心,anonymous允许无 JWT 的匿名订阅者(浏览器端订阅事件不需要鉴权);php_server { hot_reload }:在php_server指令下挂上hot_reload子指令。
从源码看(caddy/hotreload.go),configureHotReload会做两件事:把监视目录与 Mercure hub 通过frankenphp.WithHotReload()注入 PHP 线程选项;同时向每个请求注入名为FRANKENPHP_HOT_RELOAD的环境变量,其值形如/.well-known/mercure?topic=<topic>,供 PHP 侧读取订阅地址。若未配置 Mercure 就开启hot_reload,FrankenPHP 会直接报错unable to enable hot reloading: no Mercure hub configured。
默认情况下,FrankenPHP 会监视当前工作目录下匹配以下 glob 模式的所有文件:
./**/*.{css,env,gif,htm,html,jpg,jpeg,js,mjs,php,png,svg,twig,webp,xml,yaml,yml}也可以显式指定要监视的文件/目录(支持 glob 语法):
php_server { hot_reload src/**/*{.php,.js} config/**/*.yaml }或使用长格式,自定义 Mercure topic 与多个监视路径:
php_server { hot_reload { topic hot-reload-topic watch src/**/*.php watch assets/**/*.{ts,json} watch templates/ watch public/css/ } }[!WARNING] hot reload仅适用于开发环境。官方文档明确警告:该功能会暴露敏感的内部细节并拖慢应用,切勿在生产环境开启(见 docs/hot-reload.md)。
第二步:在主题的 functions.php 中注入客户端脚本
WordPress 服务端检测到文件变化后,浏览器还需要订阅事件才能完成页面更新。官方文档给出的做法是:在主题的functions.php中通过wp_head动作注入两段 JS(代码来自 docs/es/wordpress.md):
// wp-content/themes/<your-theme>/functions.php function hot_reload() { ?> <?php if (isset($_SERVER['FRANKENPHP_HOT_RELOAD'])): ?> <meta name="frankenphp-hot-reload:url" content="<?=$_SERVER['FRANKENPHP_HOT_RELOAD']?>"> <script src="https://cdn.jsdelivr.net/npm/idiomorph"></script> <script src="https://cdn.jsdelivr.net/npm/frankenphp-hot-reload/+esm" type="module"></script> <?php endif ?> <?php } add_action('wp_head', 'hot_reload');关键点说明:
$_SERVER['FRANKENPHP_HOT_RELOAD']:由 FrankenPHP 注入的环境变量(见 caddy/hotreload.go),内容为 Mercure 订阅地址。isset()判断保证未开启 hot reload 时页面零额外开销;<meta name="frankenphp-hot-reload:url" ...>:把订阅地址暴露给前端库;idiomorph:DOM morphing 库,加载后热更新会保留滚动位置与输入状态,而不是粗暴整页刷新;frankenphp-hot-reload/+esm:官方提供的前端库,自动订阅 Mercure 中心、后台拉取最新页面内容并完成 DOM 更新。
第三步:启动
一切就绪后,在 WordPress 根目录执行:
frankenphp runfrankenphp run会读取当前目录下的Caddyfile并启动 Caddy(FrankenPHP 默认在启动目录查找Caddyfile,也可用-c指定路径)。此后,无论是修改主题的functions.php、模板文件还是 CSS,浏览器都会自动刷新或 morph 更新。
进阶技巧
- 保留特定 DOM 节点:个别场景(如 Symfony Web Debug 工具条等开发工具)希望某些节点不被 morph 替换,可给对应元素加上
data-frankenphp-hot-reload-preserve属性(见 docs/hot-reload.md)。 - 与 worker 模式组合:如果你的 WordPress 应用开启了 worker 模式,PHP 常驻内存意味着改代码后 worker 不会自动重启。此时应同时配置
worker { watch }让 worker 随文件变化重启,与hot_reload形成"浏览器刷新 + worker 重启"的完整开发闭环(示例见 docs/hot-reload.md)。 - 手动实现客户端逻辑:不想引入官方 JS 库时,也可用原生
EventSource直接订阅 Mercure 中心事件(订阅路径为/.well-known/mercure?topic=...),完整的订阅与发布示例见 docs/mercure.md。
小结
围绕 WordPress 这个具体场景,FrankenPHP 给出了从"一条命令启动"到"生产级 Caddyfile"再到"开发期热重载"的完整路径:
- 快速上手:
frankenphp php-server,一条命令即可访问wp-admin完成安装; - 生产部署:
frankenphp run+Caddyfile,自动 HTTPS、HTTP/3、zstd/br/gzip 压缩一站式解决; - 开发体验:
mercure { anonymous }+php_server { hot_reload }+ 主题functions.php注入脚本,改完即所见,保留页面状态。
如需深入了解热重载的完整工作原理与全部配置项,可继续阅读 docs/hot-reload.md、docs/mercure.md 与 docs/config.md;对应实现源码位于 caddy/hotreload.go 与 caddy/php-server.go。
【免费下载链接】frankenphp🧟 The modern PHP app server项目地址: https://gitcode.com/GitHub_Trending/fr/frankenphp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考