Perf : en-têtes HTTP de cache pour les assets et les articles #18

Closed
opened 2026-05-13 22:09:32 +00:00 by cedricAbonnel · 0 comments
Owner

Problème

Les assets statiques (CSS, JS, images) et les pages d'articles ne disposent d'aucun en-tête HTTP de cache. Le navigateur refetch tout à chaque navigation, même si rien n'a changé.

Localisation

  • public/index.php — aucun en-tête Cache-Control / ETag / Last-Modified émis
  • server/apache/lan.acegrp.varlog.conf — pas de directive ExpiresActive ni mod_headers pour les assets

Solution proposée

1. Assets statiques (Apache)

Dans la config Apache, ajouter des en-têtes longs pour les fichiers immuables :

<LocationMatch "\.(css|js|svg|png|webp|woff2)$">
    Header set Cache-Control "public, max-age=31536000, immutable"
</LocationMatch>

Conditionné à l'ajout d'un fingerprint de version dans les URLs (style.css?v=abc123) pour invalider le cache lors des mises à jour — sinon max-age long est dangereux.

2. Pages articles (PHP)

Émettre Last-Modified et ETag basés sur filemtime() de index.md + meta.json, et répondre 304 Not Modified si le navigateur envoie If-Modified-Since / If-None-Match.

$lastModified = max(filemtime($mdFile), filemtime($metaFile));
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
header('Cache-Control: public, max-age=300'); // 5 min

3. Fingerprinting des assets

Dans layout.php, générer le hash du fichier CSS/JS pour le suffixer dans l'URL :

$cssVersion = substr(md5_file(BASE_PATH . /public/assets/css/style.css), 0, 8);
<link href="/assets/css/style.css?v=<?= $cssVersion ?>" rel="stylesheet">

Critères d'acceptation

  • Les assets statiques retournent Cache-Control: public, max-age=31536000 avec fingerprint dans l'URL
  • layout.php génère les URLs d'assets avec hash de contenu
  • Les pages articles retournent Last-Modified et répondent 304 si rien n'a changé
  • Les pages de brouillons ne sont pas mises en cache (Cache-Control: no-store)

Migré depuis varlog#28

## Problème Les assets statiques (CSS, JS, images) et les pages d'articles ne disposent d'aucun en-tête HTTP de cache. Le navigateur refetch tout à chaque navigation, même si rien n'a changé. ## Localisation - `public/index.php` — aucun en-tête `Cache-Control` / `ETag` / `Last-Modified` émis - `server/apache/lan.acegrp.varlog.conf` — pas de directive `ExpiresActive` ni `mod_headers` pour les assets ## Solution proposée ### 1. Assets statiques (Apache) Dans la config Apache, ajouter des en-têtes longs pour les fichiers immuables : ```apache <LocationMatch "\.(css|js|svg|png|webp|woff2)$"> Header set Cache-Control "public, max-age=31536000, immutable" </LocationMatch> ``` Conditionné à l'ajout d'un **fingerprint de version** dans les URLs (`style.css?v=abc123`) pour invalider le cache lors des mises à jour — sinon `max-age` long est dangereux. ### 2. Pages articles (PHP) Émettre `Last-Modified` et `ETag` basés sur `filemtime()` de `index.md` + `meta.json`, et répondre `304 Not Modified` si le navigateur envoie `If-Modified-Since` / `If-None-Match`. ```php $lastModified = max(filemtime($mdFile), filemtime($metaFile)); header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT'); header('Cache-Control: public, max-age=300'); // 5 min ``` ### 3. Fingerprinting des assets Dans `layout.php`, générer le hash du fichier CSS/JS pour le suffixer dans l'URL : ```php $cssVersion = substr(md5_file(BASE_PATH . /public/assets/css/style.css), 0, 8); ``` ```html <link href="/assets/css/style.css?v=<?= $cssVersion ?>" rel="stylesheet"> ``` ## Critères d'acceptation - [ ] Les assets statiques retournent `Cache-Control: public, max-age=31536000` avec fingerprint dans l'URL - [ ] `layout.php` génère les URLs d'assets avec hash de contenu - [ ] Les pages articles retournent `Last-Modified` et répondent `304` si rien n'a changé - [ ] Les pages de brouillons ne sont pas mises en cache (`Cache-Control: no-store`) --- *Migré depuis [varlog#28](https://git.abonnel.fr/cedricAbonnel/varlog/issues/28)*
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: cedricAbonnel/folio#18