...

WordPress y la caché del navegador - a menudo configurados incorrectamente

El almacenamiento en caché del navegador de WordPress a menudo causa respuestas lentas, porque los operadores tienen que Cabecera caché configurado incorrectamente o no controlado en absoluto. Le mostraré cómo las típicas configuraciones erróneas devuelven 200 en lugar de 304, por qué faltan los TTL y cómo puedo configurar correctamente el almacenamiento en caché en WordPress. Actuación recortar.

Puntos centrales

  • TTL largo para activos estáticos evita peticiones innecesarias.
  • Separación clara de rutas estáticas y dinámicas protege admin y login.
  • Un sistema no mezcle plug-ins de caché competidores.
  • Comprobar cabeceras con DevTools y estado 304.
  • Almacenamiento en caché del servidor y la caché del navegador.

Cómo funciona realmente la caché de navegador en WordPress

El navegador almacena los archivos estáticos localmente, con lo que se ahorra la necesidad de recargarlos. Peticiones HTTP. En la segunda visita, lee imágenes, CSS y JS de la memoria local y sólo pide cambios al servidor. Esto reduce la cantidad de datos, los tiempos de respuesta se reducen y el desplazamiento se siente inmediatamente más sensible. líquido en. Si no hay instrucciones claras, el navegador se recarga completamente cada vez y el tiempo de interactividad se resiente. Unas cabeceras de control de caché correctamente configuradas permiten validaciones 304, reducen el ancho de banda y la carga sobre PHP y la base de datos. Yo lo utilizo sistemáticamente porque los usuarios recurrentes, en particular, son los que más se benefician de la caché persistente.

Por qué suele fallar la configuración

Muchos sitios ofrecen archivos estáticos con una longitud ridículamente corta. max-age-valores. Algunos plugins sobrescriben los .htaccess de otros y establecen directivas contradictorias. A menudo, el sitio marca incorrectamente las rutas de administración, lo que provoca que el contenido de /wp-admin o /wp-login.php acabe en la caché involuntariamente y que las sesiones colisionen. También compruebo la diferencia entre la primera llamada y la recurrente, ya que esto explica claramente las experiencias reales de los usuarios; la comparación encaja con esto Primera llamada frente a llamada de retorno. Si sigue utilizando cadenas de consulta sin versionado, creará archivos antiguos en la memoria y se preguntará sobre obsoleto Estilos.

Configurar correctamente las cabeceras de caché de WP

Controlo la duración con Control de la caché y Expires, y evito las ETags ambiguas en entornos multiservidor. Para Apache, establezco Expires con valores significativos y defino „public, max-age“ para los activos. Para Nginx, añado directivas add_header y me aseguro de que el HTML tenga tiempos cortos o „no-store“ si el contenido es personalizado. También desactivo las cabeceras ETag si los balanceadores de carga o proxies no generan estos valores de forma coherente. De este modo, impongo un comportamiento claro en el navegador y evito Revalidaciones con cada clic.

ExpiresActive On
  ExpiresByType image/jpeg "acceso más 1 año"
  ExpiresByType image/png "acceso más 1 año"
  ExpiresByType text/css "acceso más 1 mes"
  ExpiresByType application/javascript "acceso más 1 mes"



  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)#"
  ETag de cabecera sin definir
# Nginx
location ~* .(jpg|jpeg|png|gif|ico|webp|avif|css|js|woff2?)$ {
    add_header Cache-Control "public, max-age=31536000";
}
location ~* /(wp-admin|wp-login.php)$ {
    add_header Cache-Control "no-store";
}

Directivas ampliadas de control de caché en la vida cotidiana

Además de „max-age“ y „no-store“, las directivas modernas garantizan una estabilidad notable. „immutable“ indica al navegador que un archivo no cambiará mientras el nombre del archivo siga siendo el mismo - ideal para activos versionados. „stale-while-revalidate“ permite entregar una copia caducada mientras se actualiza en segundo plano. „stale-if-error“ mantiene una copia lista si el Origen devuelve brevemente errores. „s-maxage“ está dirigido a proxies/CDNs y puede tener valores distintos de „max-age“. También importante: „public“ permite el almacenamiento en caché en proxies compartidos; „private“ está restringido al navegador. „no-cache“ no significa „no cachear“, sino „cachear permitido, pero revalidar antes de usar“ - una diferencia crucial con „no-store“.

# Apache 2.4 ejemplo (caché de activos aún más robusto)

  Conjunto de cabeceras 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)$#"
  Conjunto de cabeceras Cache-Control "no-cache, must-revalidate" "expr=%{CONTENT_TYPE} =~ m#^text/html#"
# Ejemplo Nginx (redirecciones 304/Include)
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" siempre;
}
location ~* .html$ {
    add_header Cache-Control "no-cache, must-revalidate" siempre;
}

Duraciones de caché recomendadas por tipo de archivo

Elijo los horarios en función de la frecuencia de cambio, no del hábito, porque Activos envejecen de forma muy diferente. Las imágenes, logotipos e iconos suelen permanecer actualizados durante mucho tiempo, mientras que CSS/JS reciben iteraciones más frecuentes. Las fuentes web rara vez cambian, pero requieren cabeceras CORS coherentes. El HTML suele servir de contenedor de contenidos dinámicos y, por tanto, puede durar poco o revalidarse sólo una vez. Las API deben tener reglas claramente definidas para que los clientes puedan trabajar correctamente con JSON evitar.

Tipo de fichero Recomendación Cache-Control Nota
Imágenes (jpg/png/webp/avif/svg) público, max-age=31536000 Utilizar caché anual con versionado de archivos
CSS/JS público, max-age=2592000 Añadir la versión al nombre del archivo para las actualizaciones
Fuentes (woff/woff2) público, max-age=31536000 Configurar correctamente Access-Control-Allow-Origin
HTML (páginas) no-cache, must-revalidate o short max-age Mucho cuidado con los contenidos dinámicos
API REST (json) private, max-age=0, must-revalidate Diferenciar según el criterio de valoración

Evitar conflictos con plugins

Utilizo como máximo Plugin de caché y compruebe si el alojamiento ya especifica reglas a nivel de servidor. Combinaciones como W3 Total Cache más WP Super Cache suelen crear directivas duplicadas que se anulan entre sí. WP Rocket ofrece una configuración rápida, pero necesita exclusiones claras para rutas dinámicas y comercio electrónico. En cualquier caso, compruebo el .htaccess generado después de guardarlo para reconocer cabeceras ilógicas. A continuación, pruebo las páginas críticas, como las de pago, inicio de sesión y cuadros de mando personalizados, para comprobar que son correctas. Cómo evitar.

Almacenamiento en caché y cookies: usuarios registrados, WooCommerce, sesiones

El HTML de los usuarios registrados no debe almacenarse en la caché pública. WordPress establece cookies como wordpress_logged_in_, WooCommerce complementado woocommerce_items_in_cart, wp_woocommerce_session_ y otros. En lugar de la sobre Vary: Cookie Para este tipo de solicitudes evito por completo las memorias caché. Esto mantiene los procesos de pago estables y las áreas personalizadas correctas. También utilizo reglas del servidor que establecen cabeceras más restrictivas cuando se reconocen cookies.

# Apache: Reconocimiento de cookies y configuración de cabeceras de desvío

  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: Bypass basado en cookies
if ($http_cookie ~* "(wordpress_logged_in|woocommerce_items_in_cart|wp_woocommerce_session)") {
    add_header Cache-Control "private, no-store" siempre;
}

Muchos plugins de caché ofrecen casillas de verificación para esto (WooCommerce/Cart/Exclude checkout). Importante: Nonces (_wpnonce) en los formularios y la API Heartbeat generan cambios frecuentes. Me aseguro de que el HTML del frontend con nonces no se almacene permanentemente en caché o funcione mediante „no-cache, must-revalidate“.

Tratamiento específico del HTML: personalizado frente a general

No todas las páginas son iguales. Los artículos, las páginas de destino y las páginas legales a menudo pueden almacenarse en caché con un TTL corto o revalidarse. Los archivos, las páginas de búsqueda, los cuadros de mandos, las áreas de cuentas y los checkouts siguen siendo dinámicos. Si se trata de almacenar páginas en caché, yo sigo la siguiente práctica: sólo almacenar en caché HTML público sin cookies, de lo contrario „privado“ o „sin almacenamiento“. Si está probando el micro-caché (por ejemplo, 30-60 segundos para páginas muy frecuentadas y no personalizadas), debería definir exclusiones estrictas para parámetros de consulta y sesiones. WordPress cuenta con NO REVISAR PÁGINA una constante que las plantillas pueden establecer en páginas complicadas - yo uso esto constantemente para evitar errores.

Combinar la caché del servidor con sensatez

El almacenamiento en caché del navegador termina en el cliente, pero también alivio el servidor con caché de página, objeto y opcode para real Picos de carga. El almacenamiento en caché de páginas proporciona HTML estático incluso antes de que se inicie PHP. Redis o Memcached reducen las consultas a bases de datos para peticiones repetidas y reducen notablemente el TTFB. OPcache proporciona fragmentos de bytecode PHP precompilados y acorta así el tiempo de ejecución. Al final, lo que cuenta es una conexión limpia entre la caché del servidor y la caché del navegador para que la segunda visita sea más o menos un éxito. instantánea funciona.

Integración de CDN sin sorpresas

Las CDN utilizan su propia lógica TTL y responden a „s-maxage“. Por lo tanto, hago una distinción clara: „max-age“ para navegadores, „s-maxage“ para Edge. Si hay despliegues pendientes, desencadeno una purga selectiva en lugar de destruir globalmente „Cache Everything“. Importante: Sólo cachear HTML en Edge si no hay cookies implicadas. De lo contrario, se crean estados incorrectos porque la caché Edge comparte respuestas personalizadas. Para los activos, establezco TTL largos y confío en el versionado de nombres de archivo. Las CDN pueden ignorar las cadenas de consulta, otra razón para mantener las versiones en el nombre de archivo. La normalización de las cabeceras (sin valores „Vary“ superfluos, „Content-Type“ coherente) evita que las claves de caché se hinchen.

Paso a paso: instalación limpia

Empiezo con un plugin y activo la caché del navegador para CSS, JS, imágenes y fuentes antes de activar el .htacceso finalizar. A continuación, establezco un max-age alto para los activos estáticos y proporciono HTML con tiempos cortos o reglas no-cache. Desactivo ETags si hay varios servidores implicados y confío en Last-Modified plus 304. A continuación, activo una precarga para que las páginas importantes estén disponibles inmediatamente como copias estáticas. Por último, compruebo las rutas de la tienda, de inicio de sesión y de administración para que no se almacene ningún contenido privado en la carpeta memoria intermedia tierra.

Diagnósticos prácticos con CLI y comprobaciones de cabecera

Las DevTools son obligatorias, pero yo profundizo con pruebas CLI. A curl -I muestra la cabecera sin descarga; con -H Simulo condiciones. Por ejemplo, compruebo si las revalidaciones realmente devuelven 304, si la „Edad“ aumenta desde un proxy/CDN y si las cookies desactivan el almacenamiento en caché.

# Mostrar cabecera
curl -I https://example.com/style.css

Simular la revalidación de # (If-Modified-Since)
curl -I -H "If-Modified-Since: Tue, 10 Jan 2023 10:00:00 GMT" https://example.com/style.css

Prueba # con cookie (debería forzar el bypass)
curl -I -H "Cookie: wordpress_logged_in_=1" https://example.com/

Me aseguro de que los activos tengan un valor de „control de caché“ largo, idealmente „inmutable“. El HTML debería tener „no-cache“ o un TTL corto. Si sigo obteniendo 200 en lugar de 304, a menudo hay redirecciones en juego que invalidan ETags/Last-Modified. Además, „add_header“ en Nginx sólo se aplica a las respuestas 200 por defecto - con „always“ también configuro las cabeceras para 304 y 301/302.

Comprobación y validación de cabeceras

Abro DevTools, vuelvo a cargar la página una vez, borro la caché y vuelvo a cargar para obtener 304 contra 304. 200 para observar. En el panel de red, compruebo el control de caché, la antigüedad, ETag/load-modified y los tamaños de respuesta. Si sigue habiendo visitas directas en lugar de revalidaciones, compruebo si hay conflictos con redirecciones, cookies o cadenas de consulta. Para casos complicados, me ayuda este artículo sobre trampas con las cabeceras: Sabotear la cabecera de la caché. Repito la comprobación después de cada actualización del plugin porque los cambios en las reglas suelen hacerse de forma silenciosa. pase.

Versionado, CDN y eliminación de caché

Cuelgo el Versión a los nombres de archivo (style.23.css en lugar de style.css?ver=23) para que los navegadores conserven largas cachés y sigan cargando nuevos contenidos inmediatamente. Una CDN distribuye los archivos estáticos de forma global, establece sus propios TTL en los puntos de enlace y acorta drásticamente los RTT. Importante: Sólo almacene en caché HTML en la CDN si no se requiere personalización, de lo contrario se crearán estados incorrectos. Durante el despliegue, cambio el número de versión automáticamente para que los usuarios nunca se queden atascados con scripts antiguos. Así es como combino los TTLs duros de los navegadores con los TTLs seguros. Reventar la caché.

Versiones limpias en las compilaciones de WordPress

Lo más fiable es un proceso de compilación que escriba hashes en los nombres de archivo (p. ej. app.9f3c.css). WordPress entonces carga exactamente este archivo - los navegadores pueden mantenerlo durante un año gracias a „inmutable“. Como alternativa, si los nombres de los archivos no pueden cambiarse, establezco el número de versión dinámicamente a partir de la fecha del archivo. Esto mantiene las cadenas de consulta correctas y fiables.

// functions.php (versionado fallback vía filemtime)
add_action('wp_enqueue_scripts', function () {
    $css = get_stylesheet_directory() . '/dist/style.css';
    $ver = file_exists($css) ? filemtime($css) : null;
    wp_enqueue_style('tema', get_stylesheet_directory_uri() . '/dist/style.css', [], $ver);
});

Importante: Si el nombre del archivo contiene versiones, se puede establecer „inmutable“. Si sólo utiliza cadenas de consulta, los navegadores deberían poder revalidar para que las actualizaciones lleguen de forma fiable. También me aseguro de que las herramientas de compilación limpien los archivos antiguos para que las CDN no almacenen un número innecesariamente grande de variantes.

Almacenar en caché y cargar correctamente las fuentes web

Las fuentes web necesitan TTL largos, cabeceras CORS correctas y precarga opcional para que Saltos de trazado no aparecen. Coloco los archivos woff2 en el mismo dominio o configuro Access-Control-Allow-Origin limpiamente. Además, defina font-display: swap para que el texto permanezca visible inmediatamente mientras se carga la fuente. Si quieres optimizar el tiempo de carga de tus fuentes, aquí encontrarás consejos útiles: Cargar fuentes web más rápido. Con cabeceras de caché limpias y una preconexión a CDNs, acorto notablemente FOUT/FOIT y aseguro la consistencia de Presentación-Resultados.

Ajuste correcto de fuentes, CORS y Vary

Las fuentes de otro origen requieren CORS. Configuro Access-Control-Allow-Origin (por ejemplo, a su propio dominio o „*“ para verdaderamente público) y evitar un innecesario Variar: Origen, que infla las claves de caché. Recomendado para fuentes: público, max-age=31536000, inmutable. La precarga mejora el First Paint, pero no cambia el TTL - la precarga y el hard caching se complementan. Tampoco olvido que la entrega comprimida (br/gzip) a Vary: Accept-Encoding es necesario para que los proxies se separen correctamente.

Patrones de error típicos y soluciones rápidas

Si aparece código antiguo después de una actualización, el Versionado en el nombre del archivo. Si el navegador se recarga completamente cada vez, las cabeceras establecen instrucciones contradictorias o los proxies las eliminan por el camino. Si se cancela una compra, es probable que el sitio esté almacenando en caché páginas de sesión o respuestas de la API. Si las rutas de administración se cuelan en la caché, faltan exclusiones para wp-admin e inicio de sesión o un plugin está almacenando en caché de forma global. Lo resuelvo desactivando paso a paso, consolidando cabeceras, excluyendo rutas críticas y finalmente el efecto con estado 304 confirmar.

Detalles que a menudo se pasan por alto y marcan una gran diferencia

  • Nginx add_header no se aplica a 304/redirects sin „siempre“ - entonces faltan las cabeceras de caché para las validaciones. Siempre pongo „always“.
  • Control de caducidad vs. control de caché: „Cache-Control“ tiene prioridad, „Expires“ sirve de reserva para los clientes antiguos. Evite la información duplicada y contradictoria.
  • ETag en configuraciones multiservidor: ETags inconsistentes destruyen 304. Deshabilito ETags o uso validadores débiles y confío en „Last-Modified“.
  • Variar al mínimo: „Vary: Accept-Encoding“ es obligatorio para la compresión, „Vary: Cookie“ hincha las cachés de los bordes - mejor evitar las basadas en cookies.
  • SVG y tipo MIME: Correcto imagen/svg+xml set, give long TTL and consider inline SVGs for critical icons.
  • Evite las cadenas de redireccionamiento: Cada 301/302 puede perder validadores y forzar 200 - URLs limpias sin cascadas.
  • Utilizar la prioridad/precarga de forma selectiva: fetchpriority="alta" o la precarga de activos críticos acelera la primera llamada; el almacenamiento en caché es eficaz para los usuarios que regresan.
  • Diferenciar REST-API: Los JSON públicos, que rara vez cambian, pueden almacenarse brevemente en caché; los puntos finales con tokens/cookies son estrictamente „privados“.

Brevemente resumido

Confío en la claridad ReglasTTLs largos para activos, respuestas HTML cortas o revalidadas, versionado y un único plugin de caché. A continuación, combino la caché del navegador con la caché de páginas, objetos y opcodes para reducir la carga del servidor. Compruebo DevTools, busco 304, compruebo cabeceras y elimino conflictos con redirecciones o cookies. Para la prueba práctica, comparo las mediciones de la primera llamada y de las llamadas repetidas y me centro en las mejoras perceptibles. Si sigues estos pasos, puedes hacer que WordPress alcance un nivel fiable de caché de navegador. Velocidad y mantiene contentos a los usuarios y a los motores de búsqueda.

Artículos de actualidad