Si estás tratando de mejorar la carga de tu web tarde o temprano te darás cuenta de que tienes que usar algún sistema de caché obligatoriamente.
Además, que es fácil, pues tienes montones de plugins de caché, a cual mejor. Eso sí, limitándote a usar solamente plugins de caché te estás dejando sin aplicar muchas otras mejoras de rendimiento. No debes conformarte.
Otro error común es no optimizar todo tipo de entorno, por ejemplo limitándote a optimizar solo para servidores Apache, cuando hay otros servidores como Nginx que tienen sistemas de caché enormemente óptimos, como FastCGI, que además es bastante fácil de configurar.
Yo mismo, sabes que recomiendo SiteGround como hosting especializado en WordPress, y este alojamiento siempre tiene una capa de Nginx que ¿por qué no aprovecharla también?
Índice de contenidos
La caché FastCGI de Nginx
La caché FastCGI de Nginx funciona de maravilla cuando Nginx y PHP se ejecutan en el mismo sistema, como es el caso de WordPress.
Esto es debido a que los archivos en caché tienen permisos de escritura para PHP, lo que significa que puedes vaciar la caché directamente desde PHP, algo de vital importancia cuando publicas una entrada en tu WordPress, o alguien deja un comentario, por ejemplo.
Por otro lado, Nginx siempre crea los archivos de caché mientras se realiza la ejecución de procesos por parte del usuario, lo que impide que defina el propietario o el grupo de los mismos. Es por esto que todos los archivos de la caché tienen permisos 600 para archivos y 700 para carpetas, y esto no se puede personalizar.
Esto fuerza a que cuando Nginx y PHP se ejecutan por separado ya no podrás invalidar o vaciar la caché desde PHP.
Y como no podrás personalizar los permisos de archivo en Nginx la solución es hacer que sea PHP quien cree los archivos de la caché. ¿A que está bien pensado? 😉
Y esto nos trae de vuelta a los plugins de caché para WordPress. El problema es que ninguno es especialmente eficaz aprovechando las mejoras de rendimiento que ofrece la caché FastCGI de Nginx.
¿Cómo funcionan los plugins de caché para WordPress?
Como ya deberías saber a estas alturas – si eres lector de Ayuda WordPress – el mayor cuello de botella de WordPress es la conexión con el servidor de la base de datos y las peticiones de datos necesarias para dar respuesta a las múltiples solicitudes que hace el navegador para mostrar todo su contenido dinámico.
Esto lo hace WordPress para cada petición única, da igual si los datos han cambiado o no entre las distintas peticiones. Como puedes imaginar, esto es tremendamente ineficaz, consume muchísimos recursos y provoca retardos en la respuesta, perjudicando los tiempos de carga de tus páginas.
Los plugins de caché para WordPress alivian este problema generando versiones HTML estáticas de cada petición, normalmente guardadas en el sistema de archivos.
Las siguientes peticiones servirán el HTML estático en vez de generar nuevas solicitudes de datos a la base de datos para volver a cargar la página.
Para conseguir esto los plugins de caché usan el plugin dependiente incluido en WordPress advanced-cache.php
, que se ejecuta antes de que se cargue WordPress (si la constante WP_CACHE
se ha configurado en true
). El núcleo de WordPress hace esto en wp-settings.php
:
if ( WP_CACHE && apply_filters( 'enable_loading_advanced_cache_dropin', true ) ) { // For an advanced caching plugin to use. Uses a static drop-in because you would only want one. WP_DEBUG ? include( WP_CONTENT_DIR . '/advanced-cache.php' ) : @include( WP_CONTENT_DIR . '/advanced-cache.php' ); // Re-initialize any hooks added manually by advanced-cache.php if ( $wp_filter ) { $wp_filter = WP_Hook::build_preinitialized_hooks( $wp_filter ); } }
La mayoría de los plugins de caché usan una lógica adicional en el uso de advanced-cache.php
, pero normalmente se limita únicamente a una sencilla comprobación de file_exists
, que comprueba la existencia de un archivo estático en HTML.
Si existe, su contenido se carga al paquete de salida y luego se sale del script para evitar que cargue WordPress. En este punto creo que es importante apuntar que cualquier cosa que se conecte al gancho shutdown
se seguirá ejecutando.
Esto sería un ejemplo sencillo de lo que te estoy contando:
if ( @file_exists( $path ) && @is_readable( $path ) ) { @readfile( $path ); exit; }
Por qué los plugins de caché no funcionan bien en Nginx
Aunque los plugins de caché de página para WordPress evitan la carga por defecto de WordPress y mejoran de manera notable su rendimiento, generalmente no funcionan como debieran con la caché FastCGI de Nginx.
¿A qué es debido? Sencillo, pues porque cada petición se procesa por PHP, y esto consume muchos más ciclos de CPU que si simplemente se dejase que Nginx gestionase la petición.
Cuando optimizamos para un servidor Apache, la mayoría de los plugins de caché recomiendan añadir reglas mod_rewrite
a tu archivo .htaccess
. Esto permite a Apache servir peticiones sin tener que usar PHP.
Y esto es posible porque Apache permite sobreescribir rutinas de ejecución usando archivos .htaccess
. Sin embargo, Nginx no es compatible con estos apaños.
Si pudiésemos realizar comprobaciones del tipo file_exists
como en PHP mejoraría el rendimiento de los plugins de caché para WordPress, pero desafortunadamente no es posible.
Cómo hacer que vuele tu plugin de caché
Resulta que Nginx realiza un control similar a file_exists
en cada una de las peticiones que atiende. La mayoría de las configuraciones tienen el siguiente bloque:
location / { try_files $uri $uri/ /index.php?$args; }
Esto, básicamente, le dice a Nginx que sirva el archivo solicitado si existe y que, en caso contrario, haga una redirección interna a index.php
.
Si añadimos nuestro directorio de caché a este bloque podemos indicar a Nginx que sirva el archivo HTML de la caché directamente, sin tener que usar PHP.
Si usamos, por ejemplo, el plugin Simple Cache, que almacena su caché así:
// Request: domain.com/ wp-content/cache/simple-cache/domain.com/index.html // Request: domain.com/hello-world/ wp-content/cache/simple-cache/domain.com/hello-world/index.html
Sabiendo esto, podemos actualizar nuestra directiva try_files
así:
location / { try_files "/wp-content/cache/simple-cache/${http_host}${request_uri}index.html" $uri $uri/ /index.php?$args; }
Tras volver a cargar Nginx, cualquier página de la caché generada por el plugin se servirá directamente desde Nginx sin tener que recurrir a PHP.
Las peticiones que se hayan aún almacenado en la caché las seguirá gestionando WordPress, lo que generará la caché para las siguientes peticiones.
Si usas el plugin Simple Cache en un servidor Nginx puedes/debes desactivar la opción «Activar compresión» (o cualquier otro que permita esta posibilidad) pues Nginx ya comprime automáticamente los archivos HTML antes de enviarlos la navegador. Gracias a este comportamiento por defecto de Nginx la creación de caché por PHP genera menos sobrecarga ya que no tiene que pasar por GZIP los contenidos antes de servirlos. Y este es otra de las ventajas de aprovechar las virtudes de Nginx.
Conclusiones
Si tienes la suerte de que tu hosting sirve tu web mediante Nginx no deberías desaprovechar la caché FastCGI, o al menos la combinación de try_files
y el plugin Simple Cache.
Otra posibilidad es gestionar FastCGI desde WordPress ayudándote de plugins como Nginx Cache.
En cualquier caso, debes ser consciente que la optimización web, lo conocido como técnicas WPO, no son reglas fijas para cualquier web sino que debes siempre probar y optimizar adaptándote al sistema que tienes delante, y encontrar siempre el mejor equilibrio posible entre rendimiento, consumo y uso de recursos, todo con el objetivo de optimizar al máximo el sistema para unos tiempos de carga rápidos y un uso eficiente de los recursos del servidor y sus aplicaciones.
Nota: Si tienes tu web en SiteGround el sistema de caché propio SuperCacher ya aprovecha la tecnología de caché de Nginx. No tienes que hacer nada de lo descrito en este artículo, lo tienes por defecto.
¿Te gustó este artículo? ¡Ni te imaginas lo que te estás perdiendo en YouTube!
Muy aclaratorio el artículo Fernando.
Muy interesante. Me estoy pegando intentando optimizar NGIINX en una instalación multiusuario con subdirectorios y esto me lo aclara bastante. Tengo una duda. ¿como habría que actualizar la directiva try_files con el plugion W3 total cache?