|
| 1 | +# Hot Reload |
| 2 | + |
| 3 | +FrankenPHP inclut une fonctionnalité de **hot reload** intégrée, conçue pour améliorer considérablement l'expérience développeur. |
| 4 | + |
| 5 | + |
| 6 | + |
| 7 | +Cette fonctionnalité offre un workflow similaire au **Hot Module Replacement (HMR)** présent dans les outils JavaScript modernes (comme Vite ou webpack). |
| 8 | +Au lieu de rafraîchir manuellement le navigateur après chaque modification de fichier (code PHP, templates, fichiers JavaScript et CSS...), |
| 9 | +FrankenPHP met à jour le contenu de la page en temps réel. |
| 10 | + |
| 11 | +Le Hot Reload fonctionne nativement avec WordPress, Laravel, Symfony et toute autre application ou framework PHP. |
| 12 | + |
| 13 | +Lorsqu'il est activé, FrankenPHP surveille votre répertoire de travail actuel pour détecter les modifications du système de fichiers. |
| 14 | +Quand un fichier est modifié, il envoie une mise à jour [Mercure](mercure.md) au navigateur. |
| 15 | + |
| 16 | +Selon votre configuration, le navigateur va soit : |
| 17 | + |
| 18 | +- **Transformer le DOM** (en préservant la position de défilement et l'état des champs de saisie) si [Idiomorph](https://github.com/bigskysoftware/idiomorph) est chargé. |
| 19 | +- **Recharger la page** (rechargement standard) si Idiomorph n'est pas présent. |
| 20 | + |
| 21 | +## Configuration |
| 22 | + |
| 23 | +Pour activer le hot reload, activez Mercure, puis ajoutez la sous-directive `hot_reload` à la directive `php_server` dans votre `Caddyfile`. |
| 24 | + |
| 25 | +> [!WARNING] |
| 26 | +
|
| 27 | +> Cette fonctionnalité est destinée **uniquement aux environnements de développement**. |
| 28 | +> N'activez pas `hot_reload` en production, car cette fonctionnalité n'est pas sécurisée (expose des détails internes sensibles) et ralentit l'application. |
| 29 | +
|
| 30 | +```caddyfile |
| 31 | +localhost |
| 32 | +
|
| 33 | +mercure { |
| 34 | + anonymous |
| 35 | +} |
| 36 | +
|
| 37 | +root public/ |
| 38 | +php_server { |
| 39 | + hot_reload |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +Par défaut, FrankenPHP surveillera tous les fichiers du répertoire de travail actuel correspondant au motif glob suivant : `./**/*.{css,env,gif,htm,html,jpg,jpeg,js,mjs,php,png,svg,twig,webp,xml,yaml,yml}` |
| 44 | + |
| 45 | +Il est possible de définir explicitement les fichiers à surveiller en utilisant un motif glob : |
| 46 | + |
| 47 | +```caddyfile |
| 48 | +localhost |
| 49 | +
|
| 50 | +mercure { |
| 51 | + anonymous |
| 52 | +} |
| 53 | +
|
| 54 | +root public/ |
| 55 | +php_server { |
| 56 | + hot_reload src/**/*{.php,.js} config/**/*.yaml |
| 57 | +} |
| 58 | +``` |
| 59 | + |
| 60 | +Utilisez la forme longue de `hot_reload` pour spécifier le *topic* Mercure à utiliser ainsi que les répertoires ou fichiers à surveiller : |
| 61 | + |
| 62 | +```caddyfile |
| 63 | +localhost |
| 64 | +
|
| 65 | +mercure { |
| 66 | + anonymous |
| 67 | +} |
| 68 | +
|
| 69 | +root public/ |
| 70 | +php_server { |
| 71 | + hot_reload { |
| 72 | + topic hot-reload-topic |
| 73 | + watch src/**/*.php |
| 74 | + watch assets/**/*.{ts,json} |
| 75 | + watch templates/ |
| 76 | + watch public/css/ |
| 77 | + } |
| 78 | +} |
| 79 | +``` |
| 80 | + |
| 81 | +## Intégration côté client |
| 82 | + |
| 83 | +Le serveur détecte les modifications et publie les modifications automatiquement. Le navigateur doit s'abonner à ces événements pour mettre à jour la page. |
| 84 | +FrankenPHP expose l'URL du Hub Mercure à utiliser pour s'abonner aux modifications de fichiers via la variable d'environnement `$_SERVER['FRANKENPHP_HOT_RELOAD']`. |
| 85 | + |
| 86 | +La bibliothèque JavaScript [frankenphp-hot-reload](https://www.npmjs.com/package/frankenphp-hot-reload) gére la logique côté client. |
| 87 | +Pour l'utiliser, ajoutez le code suivant à votre gabarit (*layout*) principal : |
| 88 | + |
| 89 | +```php |
| 90 | +<!DOCTYPE html> |
| 91 | +<title>FrankenPHP Hot Reload</title> |
| 92 | +<?php if (isset($_SERVER['FRANKENPHP_HOT_RELOAD'])): ?> |
| 93 | +<meta name="frankenphp-hot-reload:url" content="<?=$_SERVER['FRANKENPHP_HOT_RELOAD']?>"> |
| 94 | +<script src="https://cdn.jsdelivr.net/npm/idiomorph"></script> |
| 95 | +<script src="https://cdn.jsdelivr.net/npm/frankenphp-hot-reload/+esm" type="module"></script> |
| 96 | +<?php endif ?> |
| 97 | +``` |
| 98 | + |
| 99 | +La bibliothèque s'abonnera automatiquement au hub Mercure, récupérera l'URL actuelle en arrière-plan lorsqu'une modification de fichier est détectée et transformera le DOM. |
| 100 | +Elle est disponible en tant que package [npm](https://www.npmjs.com/package/frankenphp-hot-reload) et sur [GitHub](https://github.com/dunglas/frankenphp-hot-reload). |
| 101 | + |
| 102 | +Alternativement, vous pouvez implémenter votre propre logique côté client en vous abonnant directement au hub Mercure en utilisant la classe JavaScript native `EventSource`. |
| 103 | + |
| 104 | +### Conserver les nœuds DOM existants |
| 105 | + |
| 106 | +Dans de rares cas, comme lors de l'utilisation d'outils de développement tels que [la *web debug toolbar* de Symfony](https://github.com/symfony/symfony/pull/62970), |
| 107 | +vous pouvez souhaiter conserver des nœuds DOM spécifiques. |
| 108 | +Pour ce faire, ajoutez l'attribut `data-frankenphp-hot-reload-preserve` à l'élément HTML concerné : |
| 109 | + |
| 110 | +```html |
| 111 | +<div data-frankenphp-hot-reload-preserve><!-- Ma barre de développement --></div> |
| 112 | +``` |
| 113 | + |
| 114 | +## Mode Worker |
| 115 | + |
| 116 | +Si vous exécutez votre application en [mode Worker](worker.md), le script de votre application reste en mémoire. |
| 117 | +Cela signifie que les modifications de votre code PHP ne seront pas reflétées immédiatement, même si le navigateur recharge la page. |
| 118 | + |
| 119 | +Pour une meilleure expérience de développement, combinez `hot_reload` avec [la sous-directive `watch` dans la directive `worker`](config.md#surveillance-des-modifications-de-fichier). |
| 120 | + |
| 121 | +- `hot_reload` : rafraîchit le **navigateur** lorsque les fichiers changent |
| 122 | +- `worker.watch` : redémarre le worker lorsque les fichiers changent |
| 123 | + |
| 124 | +```caddy |
| 125 | +localhost |
| 126 | +
|
| 127 | +mercure { |
| 128 | + anonymous |
| 129 | +} |
| 130 | +
|
| 131 | +root public/ |
| 132 | +php_server { |
| 133 | + hot_reload |
| 134 | + worker { |
| 135 | + file /path/to/my_worker.php |
| 136 | + watch |
| 137 | + } |
| 138 | +} |
| 139 | +``` |
| 140 | + |
| 141 | +## Comment ça fonctionne |
| 142 | + |
| 143 | +1. **Surveillance** : FrankenPHP surveille le système de fichiers pour les modifications en utilisant [la bibliothèque `e-dant/watcher`](https://github.com/e-dant/watcher) en interne (nous avons contribué à son binding Go). |
| 144 | +2. **Redémarrage (mode Worker)** : si `watch` est activé dans la configuration du worker, le worker PHP est redémarré pour charger le nouveau code. |
| 145 | +3. **Envoi** : un payload JSON contenant la liste des fichiers modifiés est envoyé au [hub Mercure](https://mercure.rocks) intégré. |
| 146 | +4. **Réception** : le navigateur, à l'écoute via la bibliothèque JavaScript, reçoit l'événement Mercure. |
| 147 | +5. **Mise à jour** : |
| 148 | + |
| 149 | +- Si **Idiomorph** est détecté, il récupère le contenu mis à jour et transforme le HTML actuel pour correspondre au nouvel état, appliquant les modifications instantanément sans perdre l'état. |
| 150 | +- Sinon, `window.location.reload()` est appelé pour rafraîchir la page. |
0 commit comments