Kévin Dunglas 225ca409d3 feat: hot reload (#2031)
This patch brings hot reloading capabilities to PHP apps: in
development, the browser will automatically refresh the page when any
source file changes!
It's similar to HMR in JavaScript.

It is built on top of [the watcher
mechanism](https://frankenphp.dev/docs/config/#watching-for-file-changes)
and of the [Mercure](https://frankenphp.dev/docs/mercure/) integration.

Each time a watched file is modified, a Mercure update is sent, giving
the ability to the client to reload the page, or part of the page
(assets, images...).

Here is an example implementation:

```caddyfile
root ./public


mercure {
      subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY}
      anonymous
}

php_server {
      hot_reload
}
```

```php
<?php
header('Content-Type: text/html');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test</title>
<script>
    const es = new EventSource('<?=$_SERVER['FRANKENPHP_HOT_RELOAD']?>');
    es.onmessage = () => location.reload();
</script>
</head>
<body>
Hello
```

I plan to create a helper JS library to handle more advanced cases
(reloading CSS, JS, etc), similar to [HotWire
Spark](https://github.com/hotwired/spark). Be sure to attend my
SymfonyCon to learn more!

There is still room for improvement:

- Provide an option to only trigger the update without reloading the
worker for some files (ex, images, JS, CSS...)
- Support classic mode (currently, only the worker mode is supported)
- Don't reload all workers when only the files used by one change

However, this PR is working as-is and can be merged as a first step.

This patch heavily refactors the watcher module. Maybe it will be
possible to extract it as a standalone library at some point (would be
useful to add a similar feature but not tight to PHP as a Caddy module).

---------

Signed-off-by: Kévin Dunglas <kevin@dunglas.fr>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-05-31 08:01:38 +02:00
2023-12-03 19:17:36 +01:00
2025-07-17 10:14:18 +02:00
2025-11-21 13:54:07 +01:00
2025-11-21 13:54:07 +01:00
2025-11-21 13:54:07 +01:00
2025-11-21 13:54:07 +01:00
2024-10-23 22:33:58 +02:00
2025-06-25 10:18:22 +02:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-07-17 10:14:18 +02:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-08-15 00:22:44 +02:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00
2025-12-12 14:29:18 +01:00

FrankenPHP: Modern App Server for PHP

FrankenPHP

FrankenPHP is a modern application server for PHP built on top of the Caddy web server.

FrankenPHP gives superpowers to your PHP apps thanks to its stunning features: Early Hints, worker mode, real-time capabilities, automatic HTTPS, HTTP/2, and HTTP/3 support...

FrankenPHP works with any PHP app and makes your Laravel and Symfony projects faster than ever thanks to their official integrations with the worker mode.

FrankenPHP can also be used as a standalone Go library to embed PHP in any app using net/http.

Learn more on frankenphp.dev and in this slide deck:

Slides

Getting Started

On Windows, use WSL to run FrankenPHP.

Install Script

You can copy this line into your terminal to automatically install an appropriate version for your platform:

curl https://frankenphp.dev/install.sh | sh

Standalone Binary

We provide static FrankenPHP binaries for development purposes on Linux and macOS containing PHP 8.4 and most popular PHP extensions.

Download FrankenPHP

Installing extensions: Most common extensions are bundled. It's not possible to install more extensions.

rpm Packages

Our maintainers offer rpm packages for all systems using dnf. To install, run:

sudo dnf install https://rpm.henderkes.com/static-php-1-0.noarch.rpm
sudo dnf module enable php-zts:static-8.4 # 8.2-8.5 available
sudo dnf install frankenphp

Installing extensions: sudo dnf install php-zts-<extension>

For extensions not available by default, use PIE:

sudo dnf install pie-zts
sudo pie-zts install asgrim/example-pie-extension

deb Packages

Our maintainers offer deb packages for all systems using apt. To install, run:

sudo curl -fsSL https://key.henderkes.com/static-php.gpg -o /usr/share/keyrings/static-php.gpg && \
echo "deb [signed-by=/usr/share/keyrings/static-php.gpg] https://deb.henderkes.com/ stable main" | sudo tee /etc/apt/sources.list.d/static-php.list && \
sudo apt update
sudo apt install frankenphp

Installing extensions: sudo apt install php-zts-<extension>

For extensions not available by default, use PIE:

sudo apt install pie-zts
sudo pie-zts install asgrim/example-pie-extension

Homebrew

FrankenPHP is also available as a Homebrew package for macOS and Linux.

brew install dunglas/frankenphp/frankenphp

Installing extensions: Use PIE.

Usage

To serve the content of the current directory, run:

frankenphp php-server

You can also run command-line scripts with:

frankenphp php-cli /path/to/your/script.php

For the deb and rpm packages, you can also start the systemd service:

sudo systemctl start frankenphp

Docker

Alternatively, Docker images are available:

docker run -v .:/app/public \
    -p 80:80 -p 443:443 -p 443:443/udp \
    dunglas/frankenphp

Go to https://localhost, and enjoy!

Tip

Do not attempt to use https://127.0.0.1. Use https://localhost and accept the self-signed certificate. Use the SERVER_NAME environment variable to change the domain to use.

Docs

Examples and Skeletons

Description
现代 PHP 应用程序服务器
Readme MIT 44 MiB
Languages
Go 77.3%
PHP 9.3%
C 5.9%
Shell 2.5%
Dockerfile 2.4%
Other 2.6%