...

WordPress et la mise en cache du navigateur - souvent mal configurée

La mise en cache du navigateur WordPress provoque souvent des réponses lentes parce que les opérateurs En-tête du cache mal définir ou ne pas contrôler du tout. Je montre comment les erreurs de configuration typiques renvoient 200 au lieu de 304, pourquoi les TTL sont absents et comment je peux régler proprement la mise en cache dans WordPress. Performance trim.

Points centraux

  • TTL long pour les actifs statiques évite les requêtes inutiles.
  • Séparation claire de chemins statiques et dynamiques protège Admin et Login.
  • Un système configurer, ne pas mélanger des plugins de mise en cache concurrents.
  • Vérifier les en-têtes avec DevTools et assurer le statut 304.
  • Mise en cache du serveur et le cache du navigateur se combinent judicieusement.

Comment la mise en cache du navigateur fonctionne réellement dans WordPress

Le navigateur stocke les fichiers statiques en local, ce qui permet d'éviter d'avoir à les réutiliser. Requêtes HTTP. Lors de la deuxième visite, il lit les images, CSS et JS de la mémoire locale et ne demande au serveur que les modifications. Ainsi, la quantité de données diminue, les temps de réponse baissent et le défilement se sent immédiatement liquide à l'écran. En l'absence d'instructions claires, le navigateur se recharge complètement à chaque fois et le temps d'interaction en pâtit. Des en-têtes de contrôle de cache correctement définis permettent des validations 304, réduisent la bande passante et déchargent PHP et la base de données. Je l'utilise systématiquement, car ce sont justement les utilisateurs récurrents qui profitent au maximum de la mise en cache persistante.

Pourquoi la configuration échoue souvent

De nombreux sites fournissent des fichiers statiques dont la durée est ridiculement courte. max-age-de la valeur de l'adresse. Certains plugins écrasent mutuellement le .htaccess et définissent des directives contradictoires. Souvent, le site marque mal les chemins d'accès admin, ce qui fait que le contenu de /wp-admin ou /wp-login.php se retrouve involontairement dans le cache et que les sessions entrent en conflit. Je vérifie également la différence entre le premier appel et l'appel récurrent, car cela explique clairement les expériences réelles des utilisateurs ; la comparaison s'y prête bien Premier appel vs. récurrent. Si vous utilisez encore des chaînes de requête sans versionnement, vous créez de vieux fichiers en mémoire et vous vous étonnez de ce que obsolète Styles.

Définir correctement les en-têtes de cache WP

Je contrôle la durée avec Contrôle du cache et Expires, et j'évite les balises ET ambiguës dans les environnements multiserveurs. Pour Apache, je fixe des valeurs raisonnables pour Expires et je définis „public, max-age“ pour les assets. Pour Nginx, j'ajoute des directives add_header et je veille à ce que HTML obtienne des durées courtes ou „no-store“ lorsque le contenu est personnalisé. En outre, je désactive les en-têtes ETag si les répartiteurs de charge ou les proxys ne génèrent pas ces valeurs de manière cohérente. Ainsi, j'impose un comportement clair au navigateur et j'évite Revalidations à chaque clic.

ExpiresActive On
  ExpiresByType image/jpeg "access plus 1 year"
  ExpiresByType image/png "access plus 1 year"
  ExpiresByType text/css "accès plus 1 mois"
  ExpiresByType application/javascript "accès plus 1 mois"



  Header set Cache-Control "public, max-age=31536000" "expr=%{CONTENT_TYPE} =~ m#^(image/|font/|application/javascript)#"
  Header set Cache-Control "no-cache, no-store, must-revalidate" "expr=%{REQUEST_URI} =~ m#(wp-admin|wp-login.php)#"
  En-tête unset ETag
# Nginx
location ~* .(jpg|jpeg|png|gif|ico|webp|avif|css|js|woff2 ?)$ {
    add_header Contrôle de cache "public, max-age=31536000" ;
}
location ~* /(wp-admin|wp-login.php)$ {
    add_header Contrôle de cache "no-store" ;
}

Des directives de contrôle de cache avancées au quotidien

Outre „max-age“ et „no-store“, des directives modernes assurent une stabilité sensible. „immutable“ signale au navigateur qu'un fichier ne change pas tant que le nom du fichier reste le même - idéal pour les assets versionnés. „stale-while-revalidate“ permet de livrer une copie expirée pendant qu'une mise à jour est effectuée en arrière-plan. „stale-if-error“ tient une copie à disposition lorsque l'Origin fournit brièvement des erreurs. „s-maxage“ s'adresse aux proxys/CDN et peut porter d'autres valeurs que „max-age“. Important également : „public“ autorise la mise en cache dans des proxys partagés ; „private“ se limite au navigateur. „no-cache“ ne signifie pas „ne pas mettre en cache“, mais „mise en cache autorisée, mais à revalider avant utilisation“ - une différence décisive par rapport à „no-store“.

# Exemple Apache 2.4 (mise en cache des assets encore plus robuste)

  Header set Cache-Control "public, max-age=31536000, immutable, stale-while-revalidate=86400, stale-if-error=259200" "expr=%{REQUEST_URI} =~ m#.(css|js|woff2?|png|jpe?g|webp|avif)$#"
  Header set Cache-Control "no-cache, must-revalidate" "expr=%{CONTENT_TYPE} =~ m#^text/html#"
# Exemple Nginx (304/inclure les redirections)
location ~* .(css|js|woff2?|png|jpe?g|webp|avif)$ {
    add_header Cache-Control "public, max-age=31536000, immutable, stale-while-revalidate=86400, stale-if-error=259200" always ;
}
location ~* .html$ {
    add_header Contrôle de cache "no-cache, must-revalidate" always ;
}

Durées de cache recommandées par type de fichier

Je choisis les moments en fonction de la fréquence des changements, pas de l'habitude, parce que Actifs vieillissent de manière très différente. Les images, logos et icônes restent généralement à jour pendant longtemps, tandis que CSS/JS subissent des itérations plus fréquentes. Les polices Web changent rarement, mais nécessitent des en-têtes CORS cohérents. Le HTML sert souvent de conteneur pour les contenus dynamiques et peut donc être court ou seulement révisé. Les API devraient recevoir des règles clairement définies afin que les clients puissent utiliser correctement les JSON contourner.

Type de fichier Recommandation de contrôle du cache Remarque
Images (jpg/png/webp/avif/svg) public, max-age=31536000 Utiliser le cache annuel avec le versionnement des fichiers
CSS/JS public, max-age=2592000 Ajouter la version au nom de fichier pour les mises à jour
Fontes (woff/woff2) public, max-age=31536000 Définir correctement l'origine du contrôle d'accès Allow
HTML (pages) no-cache, must-revalidate ou max-age court Très prudent avec les contenus dynamiques
API REST (json) private, max-age=0, must-revalidate Différencier selon le point final

Éviter les conflits avec les plugins

Je mets tout au plus Plugin de mise en cache et vérifier que l'hébergement n'impose pas déjà des règles au niveau du serveur. Des combinaisons telles que W3 Total Cache plus WP Super Cache génèrent souvent des directives doubles qui s'annulent mutuellement. WP Rocket offre une mise en place rapide, mais nécessite des exclusions claires pour les chemins dynamiques et le commerce électronique. Dans tous les cas, je contrôle le .htaccess généré après l'avoir enregistré afin de détecter les en-têtes illogiques. Ensuite, je teste les pages critiques comme le checkout, le login et les tableaux de bord personnalisés pour vérifier qu'ils sont corrects. Contournement.

Caching et cookies : utilisateurs connectés, WooCommerce, sessions

Le HTML pour les utilisateurs connectés ne doit pas se retrouver dans le cache public. WordPress utilise des cookies tels que wordpress_logged_in_, WooCommerce complété woocommerce_items_in_cart, wp_woocommerce_session_ et d'autres. Au lieu d'utiliser le système de Vary : Cookie je contourne complètement les caches pour ces demandes. Ainsi, les processus de caisse restent stables et les zones personnalisées sont correctes. En outre, j'utilise des règles côté serveur qui définissent des en-têtes plus restrictifs en cas de détection de cookies.

# Apache : détecter les cookies et définir des en-têtes de contournement

  SetEnvIfNoCase Cookie "wordpress_logged_in_|woocommerce_items_in_cart|wp_woocommerce_session" has_session
  Header set Cache-Control "private, no-store" env=has_session
# Nginx : contournement basé sur les cookies
if ($http_cookie ~* "(wordpress_logged_in|woocommerce_items_in_cart|wp_woocommerce_session)") {
    add_header Contrôle de cache "private, no-store" always ;
}

De nombreux plugins de mise en cache proposent des cases à cocher à cet effet (WooCommerce/Cart/Checkout exclure). Important : les nonces (_wpnonce) dans les formulaires et l'API Heartbeat génèrent des modifications fréquentes. Je m'assure que le HTML frontal avec nonces n'est pas mis en cache de manière permanente ou fonctionne par „no-cache, must-revalidate“.

Traiter le HTML de manière ciblée : personnalisé vs. général

Toutes les pages ne sont pas identiques. Les articles, les pages de renvoi et les pages juridiques peuvent souvent être mis en cache avec un TTL court ou une revalidation. Les archives, les pages de recherche, les tableaux de bord, les zones de compte et les checkouts restent dynamiques. Si la mise en cache de pages est en jeu, je respecte la pratique suivante : mettre en cache le HTML public uniquement sans cookies, sinon „privé“ ou „no-store“. Ceux qui testent la micro-caching (par exemple 30-60 secondes pour des pages très fréquentées et non personnalisées) devraient définir des exclusions strictes pour les paramètres de requête et les sessions. WordPress possède avec DONOTCACHEPAGE une constante que les templates peuvent mettre sur des pages délicates - je l'utilise systématiquement pour éviter les erreurs.

Combiner judicieusement la mise en cache côté serveur

La mise en cache du navigateur s'arrête au client, mais je décharge en plus le serveur avec la mise en cache des pages, des objets et des opcodes pour de véritables Pics de charge. La mise en cache de pages fournit du HTML statique avant même que PHP ne démarre. Redis ou Memcached réduisent les requêtes répétées dans la base de données et diminuent sensiblement le TTFB. OPcache tient à disposition des fragments de bytecode PHP précompilés et réduit ainsi le temps d'exécution. En fin de compte, ce qui compte, c'est la connexion propre du cache du serveur et du cache du navigateur, afin que la deuxième visite soit pour ainsi dire "normale". instantané agit.

Intégration CDN sans surprise

Les CDN utilisent leur propre logique TTL et réagissent à „s-maxage“. Je fais donc une distinction claire : „max-age“ pour le navigateur, „s-maxage“ pour Edge. Si des déploiements sont prévus, je déclenche une purge ciblée au lieu de détruire globalement „Cache Everything“. Important : ne mettre en cache le HTML sur Edge que si aucun cookie n'est impliqué. Dans le cas contraire, des états erronés apparaissent, car le cache de l'Edge partage des réponses personnalisées. Pour les assets, je définis des TTL longs et je me fie au versionnement des noms de fichiers. Les CDN peuvent ignorer les chaînes de requête - une autre raison de préférer porter les versions dans le nom de fichier. La normalisation des en-têtes (pas de valeurs „Vary“ superflues, „Content-Type“ cohérent) évite les clés de cache gonflées.

Pas à pas : une installation propre

Je commence par un plugin et j'y active la mise en cache du navigateur pour CSS, JS, les images et les polices, avant de .htaccess pour la finaliser. Ensuite, j'augmente le max-age pour les actifs statiques et j'ajoute des temps courts ou des règles de non-cache au HTML. Je désactive les balises ET si plusieurs serveurs sont impliqués et je me fie à Last-Modified plus 304. Je déclenche ensuite un préchargement pour que les pages importantes soient immédiatement disponibles en tant que copies statiques. Enfin, je vérifie les chemins d'accès à la boutique, au login et à l'administration afin d'éviter que des contenus privés ne soient publiés sur le site. mémoire tampon atterrir.

Diagnostic pratique avec CLI et Header-Checks

DevTools sont obligatoires, mais je vais plus loin avec les tests CLI. Un curl -I montre les en-têtes sans téléchargement ; avec -H je simule des conditions. Ainsi, je vérifie si les revalidations renvoient vraiment 304, si „Age“ augmente depuis un proxy/CDN et si les cookies désactivent la mise en cache.

# Afficher l'en-tête
curl -I https://example.com/style.css

# Simuler une revalidation (If-Modified-Since)
curl -I -H "If-Modified-Since : Tue, 10 Jan 2023 10:00:00 GMT" https://example.com/style.css

# Tester avec un cookie (devrait forcer le bypass)
curl -I -H "Cookie : wordpress_logged_in_=1" https://example.com/

Je veille à ce que les actifs portent une longue valeur de „contrôle du cache“, idéalement „immutable“. Le HTML devrait avoir „no-cache“ ou un TTL court. Si j'obtiens malgré tout 200 au lieu de 304, il s'agit souvent de redirections qui invalident les ETags/Last-Modified. De même, „add_header“ dans Nginx ne s'applique par défaut qu'aux réponses de 200 - avec „always“, je définis les en-têtes également pour 304 et 301/302.

Test et validation des en-têtes

J'ouvre DevTools, je charge une fois la page, j'efface le cache et je charge à nouveau pour trouver 304 en face. 200 d'observer la situation. Dans le panneau de réseau, je contrôle le contrôle du cache, l'âge, l'ETag/le dernier modifié et la taille des réponses. Si, malgré tout, des réponses positives apparaissent au lieu de revalidations, je vérifie les conflits avec les redirections, les cookies ou les chaînes de requête. Pour les cas délicats, cet article sur les pièges des en-têtes m'aide : Saboter les en-têtes de cache. Après chaque mise à jour de plugin, je répète le contrôle, car les modifications des règles sont souvent implicites. passer.

Versioning, CDN et cache busting

J'accroche les Version aux noms de fichiers (style.23.css au lieu de style.css?ver=23), afin que les navigateurs conservent de longs caches tout en chargeant immédiatement les nouveaux contenus. Un CDN distribue les fichiers statiques de manière globale, définit ses propres TTL dans les Edge-PoPs et raccourcit drastiquement les RTT. Important : ne mettre en cache le HTML dans le CDN que si aucune personnalisation n'est nécessaire, sinon des états erronés apparaissent. Lors du déploiement, je modifie automatiquement le numéro de version afin que les utilisateurs ne soient jamais bloqués par d'anciens scripts. Je combine ainsi des TTL de navigateur durs avec des TTL sécurisés. Cache-busting.

Versionnement propre dans les builds WordPress

Le plus fiable est un pipeline de construction qui écrit les hachages dans les noms de fichiers (par exemple. app.9f3c.css). WordPress charge alors exactement ce fichier - les navigateurs peuvent le garder un an grâce à „immutable“. Comme solution de repli, lorsque les noms de fichiers ne peuvent pas être modifiés, je définis le numéro de version de manière dynamique à partir de la date du fichier. Ainsi, les chaînes de requête restent correctes et fiables.

// functions.php (versionnement de repli via filemtime)
add_action('wp_enqueue_scripts', function () {
    $css = get_stylesheet_directory() . '/dist/style.css' ;
    $ver = file_exists($css) ? filemtime($css) : null ;
    wp_enqueue_style('theme', get_stylesheet_directory_uri() . '/dist/style.css', [], $ver) ;
}) ;

Important : si le nom de fichier porte des versions, il est possible de mettre „immutable“. Si l'on n'utilise que des chaînes de requête, les navigateurs doivent être capables de revalider pour que les mises à jour arrivent de manière fiable. Je veille également à ce que les outils de construction nettoient les anciens fichiers, afin que les CDN ne stockent pas inutilement de nombreuses variantes.

Mettre en cache et charger correctement les polices web

Les polices web ont besoin de longs TTL, d'en-têtes CORS corrects et, en option, de préchargement pour que Sauts de mise en page ne se produisent pas. Je place les fichiers woff2 sur le même domaine ou je définis proprement Access-Control-Allow-Origin. En outre, je définis font-display : swap pour que le texte reste immédiatement visible pendant le chargement de la police. Si vous souhaitez optimiser le temps de chargement de vos polices de manière ciblée, vous trouverez ici des indications utiles : Chargement plus rapide des polices web. Grâce à des en-têtes de cache propres et à une préconnexion aux CDN, je raccourcis considérablement le FOUT/FOIT et garantis une connexion cohérente. Rendu-résultats.

Accorder correctement les polices, CORS et Vary

Les polices d'une autre origine nécessitent CORS. Je mets Access-Control-Allow-Origin de manière ciblée (par exemple sur son propre domaine ou „*“ pour truly public) et évite de créer inutilement un Vary : Origine, qui gonfle les clés de cache. Pour les polices, il est recommandé public, max-age=31536000, immutable. Preload améliore First Paint, mais ne change rien à la TTL - Preload et hard caching se complètent. Je n'oublie pas non plus que la livraison compressée (br/gzip) un Vary : Accept-encodage est nécessaire pour que les proxys se séparent correctement.

Erreurs typiques et solutions rapides

Si un ancien code arrive après une mise à jour, il manque souvent le Versionnement au nom du fichier. Si le navigateur se recharge complètement à chaque fois, les en-têtes définissent des instructions contradictoires ou les proxys les suppriment en cours de route. Si un checkout s'interrompt, le site met probablement en cache des pages de session ou des réponses API. Si les chemins d'accès admin glissent dans le cache, il manque des exclusions pour wp-admin et Login ou un plugin met globalement en cache. Je résous ce problème en désactivant progressivement, en consolidant les en-têtes, en excluant les chemins critiques et en finissant par l'effet 304. confirme.

Des détails souvent négligés qui font toute la différence

  • Nginx add_header ne s'applique pas aux 304/redirections sans „always“ - il manque alors des en-têtes de cache pour les validations. Je mets systématiquement „always“.
  • Expires vs. Contrôle du cache : „Cache-Control“ a la priorité, „Expires“ sert de repli pour les anciens clients. Éviter les indications doubles et contradictoires.
  • ETag dans les configurations multiserveurs : Les balises ET incohérentes détruisent les 304. Je désactive les balises ET ou j'utilise des validateurs faibles et je me fie à „Last-Modified“.
  • Vary au minimum : „Vary : Accept-Encoding“ est obligatoire en cas de compression, „Vary : Cookie“ fait gonfler les caches Edge - il vaut mieux contourner par cookie.
  • SVG et type MIME : Correct image/svg+xml donner des TTL longs et envisager des SVG en ligne pour les icônes critiques.
  • Éviter les chaînes de redirection : Chaque 301/302 peut perdre des validateurs et en forcer 200 - des URL propres sans cascades.
  • Utiliser la priorité/le préchargement de manière ciblée : fetchpriority="high" (priorité de frappe) ou Preload pour les assets critiques accélère le premier appel ; la mise en cache agit sur le récurrent.
  • différencier l'API REST : Les JSON publics, qui changent rarement, peuvent être mis en cache brièvement ; les points de terminaison avec jetons/cookies strictement „privés“.

En bref

Je mise sur la clarté Règles: des TTL longs pour les assets, des réponses HTML courtes ou révisées, le versioning et un seul plugin de mise en cache. Ensuite, je combine le cache du navigateur avec le cache des pages, des objets et des opcodes pour réduire la charge du serveur. Je vérifie DevTools, je regarde les 304, je contrôle les en-têtes et j'élimine les conflits avec les redirections ou les cookies. Pour le test pratique, je compare les mesures lors du premier appel et des appels répétés et je me concentre sur les améliorations sensibles. En suivant ces étapes, WordPress peut être mis en cache de manière fiable dans le navigateur. Vitesse et maintient la satisfaction des utilisateurs comme des moteurs de recherche.

Derniers articles