fix: serve a fresh JavaScript after a deployment (cache policy + asset version marker) #173
No reviewers
Labels
No labels
auto-merge
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
AcadeNice/corentin_wakdo!173
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/asset-cache-busting"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Le defaut
Apres une mise en production, un navigateur pouvait continuer a executer l'ANCIEN JavaScript.
Mesure sur la production,
/assets/js/product-recipe.js: aucun en-teteCache-Control, seulementETagetLast-Modified. SansCache-Control, un navigateur applique une fraicheur heuristique (RFC 9111 4.2.2, couramment un dixieme de l'age du document) et reutilise le fichier plusieurs heures sans revalider.ETagne sert que si le navigateur decide de revalider -- ce que la fraicheur heuristique lui evitait justement. Apres la refonte du back-office, l'ancien JS tournait donc contre le nouveau HTML : les boutons ne faisaient rien, sans erreur visible.La correction, en deux morceaux
1. Une politique de cache explicite --
docker/apache/cache.conf, ecrite une fois, incluse par les deux vhosts (borne et back-office).?v=...public, max-age=31536000, immutableno-cache(revalidation, 304 si inchange)public, max-age=604800(inchange)no-cacheno-store, private2. Un marqueur de version dans l'adresse --
App\Core\Asset, une seule fonction d'aide, injectee comme$asset()dans toute vue parApp\Core\Controller. Aucun suffixe recopie a la main : une garde de test refuse toute adresse/assets/...ecrite en dur dans un attribut de vue.Le marqueur est le SHA court deploye, lu dans
src/VERSION(ecrit parscripts/deploy.sh, deja expose parGET /api/health). Repli sur la date de modification du fichier quandsrc/VERSIONest absent (installation locale, pile de test -- il est ignore par git), puis aucun marqueur si rien n'est mesurable.Mesures, avant et apres (pile jetable)
admin /assets/js/product-recipe.jsno-cacheadmin /assets/js/product-recipe.js?v=...public, max-age=31536000, immutableadmin /assets/css/admin.cssno-cacheadmin /loginno-store, no-cache, must-revalidateno-store, privateborne /products.htmlno-cacheborne /assets/css/style.cssno-cacheborne /assets/images/.../burgers.pngpublic, max-age=604800public, max-age=604800Adresse rendue dans
/login, bout en bout :Tests (ecrits avant le code)
tests/Unit/Core/AssetTest.php, 14 cas : presence du marqueur, changement de version, stabilite,src/VERSIONabsent / vide / corrompu, adresse deja porteuse d'une chaine de requete, chemin remontant, jamais de marqueur vide, plus la garde d'usage sur les vues.Suite complete : PHPUnit 1698 tests verts, PHPStan niveau 6 sans erreur, 356 tests JS verts.
Ce que ce lot ne couvre pas
src/public/borne/*.htmlest du HTML statique servi tel quel : sans etape de construction, ses adresses ne peuvent pas porter de marqueur. Elle retombe surno-cache-- correct (le defaut est corrige), juste moins econome en allers-retours.git pulla la main qui contournescripts/deploy.shlaisseraitsrc/VERSIONinchange : le marqueur ne bougerait pas alors que le code a change. Le chemin documente (deploy.sh, aussi declenche par le CD) reecrit toujourssrc/VERSION.script-src 'self') : le marqueur est une chaine de requete, aucun script en ligne n'a ete introduit.