v2.6.3 : cache-busting des assets (jeton ?v= = version, injecte par le serveur)

index.html reference css/js en ?v=__V__ ; handleStatic remplace __V__ par
APP_VERSION dans les reponses .html. Chaque deploiement change le jeton ->
le navigateur recharge le nouveau code sans vider le cache (cause du
'toujours pas' : ancien treasures.js en cache qui lisait le statique sans
les bonus magiques edites en base).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
perco
2026-06-13 23:43:25 +02:00
co-authored by Claude Opus 4.8
parent 55b573001b
commit b55a6f8ac9
4 changed files with 29 additions and 10 deletions
+7
View File
@@ -234,6 +234,13 @@ non affilié au jeu original de Mountyhall SARL.
## Versions ## Versions
- **2.6.3** (2026-06-13) — **Cache-busting** des fichiers du jeu : les balises
`<script>`/`<link>` de `index.html` portent `?v=__V__`, jeton que le serveur
remplace par la version de l'appli (donc différent à chaque déploiement). Le
navigateur recharge ainsi forcément le nouveau code/CSS — fini les anciennes
versions servies depuis le cache même après une mise à jour (par ex. la page
« Trésors du Hall » qui n'affichait pas les bonus magiques d'équipement
fraîchement édités). Complète le `Cache-Control: no-cache` de la 2.6.1.
- **2.6.2** (2026-06-13) — La page admin et l'édition directe en base - **2.6.2** (2026-06-13) — La page admin et l'édition directe en base
(sqlite-web) **ne se marchent plus dessus**. Avant, sauver le tuning d'une (sqlite-web) **ne se marchent plus dessus**. Avant, sauver le tuning d'une
catégorie la **remettait entièrement au vanilla** puis réappliquait le catégorie la **remettait entièrement au vanilla** puis réappliquait le
+9 -9
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MountyCrawl — Le Monde Souterrain</title> <title>MountyCrawl — Le Monde Souterrain</title>
<link rel="stylesheet" href="css/style.css"> <link rel="stylesheet" href="css/style.css?v=__V__">
</head> </head>
<body> <body>
@@ -227,13 +227,13 @@
<footer id="app-footer" class="app-footer" aria-label="Version"></footer> <footer id="app-footer" class="app-footer" aria-label="Version"></footer>
<script src="js/potions.js"></script> <script src="js/potions.js?v=__V__"></script>
<script src="js/scrolls.js"></script> <script src="js/scrolls.js?v=__V__"></script>
<script src="js/gear.js"></script> <script src="js/gear.js?v=__V__"></script>
<script src="js/game.js"></script> <script src="js/game.js?v=__V__"></script>
<script src="js/editor.js"></script> <script src="js/editor.js?v=__V__"></script>
<script src="js/mp-client.js"></script> <script src="js/mp-client.js?v=__V__"></script>
<script src="js/rules.js"></script> <script src="js/rules.js?v=__V__"></script>
<script src="js/treasures.js"></script> <script src="js/treasures.js?v=__V__"></script>
</body> </body>
</html> </html>
+1 -1
View File
@@ -4,7 +4,7 @@
"use strict"; "use strict";
const APP_VERSION = "2.6.2"; const APP_VERSION = "2.6.3";
/* Alpha : maîtrise initiale haute pour les tests. Remettre 15 % / 15 % à la v1.0 officielle. */ /* Alpha : maîtrise initiale haute pour les tests. Remettre 15 % / 15 % à la v1.0 officielle. */
const START_COMP_PCT = 90; const START_COMP_PCT = 90;
+12
View File
@@ -15,6 +15,15 @@ const db = require("./db.js");
const PORT = process.env.PORT || 80; const PORT = process.env.PORT || 80;
const ROOT = __dirname; const ROOT = __dirname;
// Jeton de cache-busting injecté dans le HTML (assets référencés en `?v=__V__`) :
// il vaut la version de l'appli, donc change à chaque déploiement → le navigateur
// recharge forcément le nouveau code/CSS sans vider son cache à la main.
const BUILD = (() => {
try {
const m = fs.readFileSync(path.join(__dirname, "js/game.js"), "utf8").match(/APP_VERSION\s*=\s*["']([^"']+)["']/);
return m ? m[1] : String(Date.now());
} catch { return String(Date.now()); }
})();
const LEVELS_FILE = process.env.LEVELS_FILE || "/data/levels.json"; const LEVELS_FILE = process.env.LEVELS_FILE || "/data/levels.json";
const WORLD_FILE = process.env.WORLD_FILE || "/data/world.json"; const WORLD_FILE = process.env.WORLD_FILE || "/data/world.json";
const DB_FILE = process.env.DB_FILE || "/data/mountycrawl.db"; const DB_FILE = process.env.DB_FILE || "/data/mountycrawl.db";
@@ -341,6 +350,9 @@ function handleStatic(req, res, url) {
fs.readFile(file, (err, data) => { fs.readFile(file, (err, data) => {
if (err) { res.writeHead(404); return res.end("introuvable"); } if (err) { res.writeHead(404); return res.end("introuvable"); }
const ext = path.extname(file); const ext = path.extname(file);
// Pages HTML : on remplace le jeton de cache-busting des assets (`?v=__V__`)
// par la version courante.
if (ext === ".html") data = Buffer.from(data.toString("utf8").replace(/__V__/g, BUILD));
// Code et pages (.html/.js/.css) : toujours revalider pour qu'une mise à // Code et pages (.html/.js/.css) : toujours revalider pour qu'une mise à
// jour (ou une édition de la base reflétée par le code) soit prise tout de // jour (ou une édition de la base reflétée par le code) soit prise tout de
// suite, sans cache navigateur périmé. Médias : cache court. // suite, sans cache navigateur périmé. Médias : cache court.