# En-têtes Cache-Control et ETag mal réglés sur les assets statiques WordPress

> Un audit de dix sites clients révèle des CSS et JS servis sans cache navigateur correct. Checklist des réglages nginx et Apache pour ne jamais retélécharger deux fois le même fichier.

- Auteur : Clément Hadrot
- Publié le : 2021-06-16
- Mis à jour le : 2021-06-16
- Catégorie : Performance
- URL : https://wpmoderne.dev.wordpress-developpement.fr/performance/cache-control-etag-assets-statiques-checklist/

## L’essentiel

- Un fichier CSS versionné doit être caché longtemps, un an ou plus
- ETag mal configuré force une revalidation inutile à chaque visite
- Le réglage se fait au niveau du serveur web, pas dans WordPress

Un audit de performance mené sur dix sites clients hébergés chez trois prestataires différents a révélé un constat surprenant : aucun des dix ne réglait correctement les en-têtes de cache navigateur pour ses fichiers CSS et JavaScript. Certains ne renvoyaient aucun `Cache-Control`, d'autres renvoyaient une durée de quelques minutes seulement, et un site renvoyait un `ETag` qui changeait à chaque redémarrage du serveur, rendant tout cache navigateur inefficace en pratique.

Ce défaut ne se voit pas dans Lighthouse au premier chargement d'une page, puisqu'il ne concerne que les visites suivantes. C'est justement ce qui le rend facile à manquer lors d'un audit rapide, alors qu'il pénalise directement l'expérience des visiteurs récurrents, souvent les plus engagés d'un site.

## Ce que doit faire un bon réglage de cache

Les fichiers CSS et JavaScript générés par un thème ou une extension WordPress portent presque toujours un numéro de version dans leur nom de fichier ou en paramètre d'URL, via `wp_enqueue_style()` et `wp_enqueue_script()`. Cela signifie qu'un changement de contenu du fichier s'accompagne mécaniquement d'un changement d'URL, ce qui permet de mettre en cache ces ressources pendant une très longue durée, souvent un an, sans risque de servir une version obsolète après une mise à jour.

## La checklist de vérification

Voici les points contrôlés systématiquement sur chacun des dix sites de l'audit, dans l'ordre :

- Présence d'un en-tête `Cache-Control: max-age=31536000, immutable` ou équivalent sur les fichiers CSS, JS, polices et images versionnés.
- Absence d'en-tête `ETag` incohérent qui changerait sans changement réel de contenu, notamment après chaque redémarrage de PHP-FPM sur certaines configurations.
- Vérification que les fichiers non versionnés, comme un fichier de configuration texte, ne sont pas mis en cache aussi longtemps que les assets versionnés.
- Test réel avec les outils réseau du navigateur, en rechargeant la page pour confirmer un statut `200 (from disk cache)` plutôt qu'un aller-retour vers le serveur.

> L'essentiel à retenir : Un fichier CSS versionné doit être caché longtemps, un an ou plus ; ETag mal configuré force une revalidation inutile à chaque visite ; Le réglage se fait au niveau du serveur web, pas dans WordPress

## Le réglage sous nginx

Sur les sites servis par nginx, le bloc suivant, placé dans la configuration du site, a résolu la majorité des cas observés :

```
location ~* \.(css|js|woff2|jpg|jpeg|png|webp)$ {
    expires 365d;
    add_header Cache-Control "public, immutable";
    access_log off;
}
```

Le mot-clé `immutable` indique au navigateur qu'il n'a même pas besoin de revalider le fichier auprès du serveur avant la fin de la durée de cache, ce qui économise une requête de vérification conditionnelle à chaque visite.

## Le réglage sous Apache

Pour les sites hébergés sur Apache, le module `mod_expires` a permis un réglage équivalent dans le `.htaccess` ou la configuration de l'hôte virtuel :

```
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"
    ExpiresByType font/woff2 "access plus 1 year"
</IfModule>
```

## Le piège de l'ETag mal configuré

Sur l'un des sites audités, l'ETag était généré à partir de l'inode du fichier sur le serveur, un réglage par défaut de certaines configurations Apache sur des architectures avec plusieurs serveurs applicatifs en répartition de charge. Chaque serveur générait un inode différent pour un fichier pourtant identique, ce qui forçait le navigateur à retélécharger la ressource selon le serveur qui répondait à la requête. La désactivation complète de l'ETag au profit d'un `Cache-Control` long a résolu ce cas précis :

```
FileETag None
```

## Pour aller plus loin

Ce réglage ne concerne que le cache navigateur des ressources statiques, pas le cache de la page HTML elle-même, qui suit une logique différente et beaucoup plus courte, incompatible avec une mise en cache d'un an. Confondre les deux est une autre erreur fréquente observée pendant cet audit, mais qui dépasse le cadre de cette checklist.

## En résumé

Un réglage correct de `Cache-Control` et d'`ETag` sur les assets statiques est l'un des gains de performance les plus simples à obtenir sur un site WordPress existant, puisqu'il ne touche à aucun code applicatif. Il se règle une seule fois au niveau du serveur web et bénéficie à chaque visiteur récurrent, pour un coût de mise en œuvre proche de zéro.
