Internet, Informática y Tecnología

Optimización y configuración de WordPress a fondo e insana

Nota: La entrada es un borrador por lo que aún no está terminada, puede tener errores de ortografía y gramática. Nota: Los puntos directamente relacionados con WordPress fueron probados con la versión 3.*, no se garantiza que estos funcionen en las versiones más recientes.

WordPress como todos sabemos, uno de los CMS más utilizados para crear desde Blogs hasta sitios de Noticias, o sitios fuera de lo común, siendo tan popular todos sabemos que de forma predeterminada no se comporta como nos gustaría. Esto principalmente es porque tiene muy pocas opciones, y normalmente tenemos que recurrir a guías para lograr nuestro objetivo o al menos para que funcione de manera estable cuando hablamos de un sitio pesado con muchos plugins.

El objetivo de este tutorial o guía es recopilar desde cosas muy sencillas pero útiles, hasta cosas avanzadas que pueden evitarnos dolores de cabeza cuando nos va bien.

Consejos y aclaraciones

Primero empezaré con los consejos y aclaraciones.

  • ¿Tener muchos plugins desactivados afecta en el rendimiento de WordPress? No, solo afecta al momento de cargar la lista de estos mismos.
  • ¿Tener muchos plugins activados hace que mi blog se ponga lento? Depende, por lo general los Plugins son muy pesados y específicos, siendo de este tipo la mayoría entonces sí, de lo contrario sin tenemos muchos plugins livianos no se vería afectado nuestro sitio.

Utilidades

Este tipo de necesidades normalmente son muy específicas, pero siempre es bueno tenerlas a la mano. Lista de mini plugins o código útiles:

  • Desactivar Feeds: https://wordpress.org/extend/plugins/disable-feeds/
  • Abrir enlaces de comentarios en una nueva página (enlace de autor): wp-comment-author-link-blank-page.zip
  • Eliminar/Desactivar shortlink del HTML Head y de los Headers: wp-remove-shortlink.zip
  • Eliminar WP Generator de los meta HTML
  • Eliminar/Desactivar X-Pingback de los Headers
  • Activar Gestor de Enlaces
  • Quitar/Agregar párrafos automáticos <p>:
  • Leer más personalizado
  • Número personalizado de palabras en los extractos/resúmenes
  • Extracto personalizado de número de palabras en los Feeds

Optimización y rendimiento

La optimización de un sitio con WordPress no necesariamente se necesita cuando tenemos muchas visitas, es igualmente importante en un sitio con muy pocas visitas, ya que no es la misma esperar a que una página se genere en 200 ~ 400 ms, que a que sea obtenida directamente desde algún sistema de caché, o bien si aun no queremos utilizar caché, podríamos fácilmente reducir ese retraso para aumentar el número de visitas soportado por nuestro servidor.

Primeramente la optimización más necesaria desde un punto de vista personal, es el procesamiento de lado del cliente, lo que la mayoría del tiempo es más lento. Sin descartar nada, el principal cuello de botella de un sitio web es la red, por lo que es necesario reducir los datos que se transferirán al cliente en cada petición, la mejor manera de hacerlo es:

Reduciendo el tamaño de las imágenes

Para reducir el tamaño de nuestras imágenes, podemos utilizar servicios como Yahoo Smushit que nos permite hacerlo sin descargar ningún tipo de programa, para comprimir las imágenes sin pérdida de calidad, antes de subirlas a nuestros artículos. En el caso de las imágenes que son parte del diseño de nuestro sitio, es igualmente importante reducir su peso, ya que en cada petición estas son cargadas junto con el contenido. El formato óptimo para el logotipo es PNG, ya que para pocos colores la compresión que utiliza es bastante eficiente, soporta transparencia y no hay pérdida de calidad. Si tenemos Favicon también es importante usar pocos colores y un tamaño máximo de 24 x 24, un mayor tamaño sería inútil y consumiría un poco más de ancho de banda.

Utilizando miniaturas en lugar de imágenes a escala mediante HTML

Cuando usamos imágenes grandes escaladas para que parezcan miniaturas, además de un pobre rendimiento en los navegadores web, los datos transferidos son altos, siendo que se podrían evitar si usamos diferentes tamaños de imágenes de una misma, y no una escalada en varios tamaños mediante HTML. Existen algunas herramientas como Paint.Net con las que podemos crear varios tamaños de las imágenes, o también podemos modificar en WordPress el tamaño por defecto de los diferentes tipos de imágenes que se crean al subir una nueva imagen en Ajustes > Media, y podemos elegir tres tamaños que serían una miniatura, tamaño medio, y tamaño grande.

Minimizar el código HTML

Además de la compresión gzip que se aplica al momento de enviar una página, es igualmente útil reducir cada carácter no necesario de nuestras páginas, y esto con el fin de reducir el tiempo en el que estas se transfieren hacia el cliente. Para hacerlo podemos editar nuestros Temas y simplemente reducir espacios y tabulaciones excesivas, pero como para algunos esto no es eficiente, podemos usar plugins como https://wordpress.org/plugins/wp-html-compression/, que se encargan de esto automáticamente, con soporte para desactivarlo en ciertas secciones delicadas (anuncios, etc.).

Minimizar los archivos CSS y JS

La mayoría de sitios cuentan con al menos un archivo CSS y/o un JS, por lo que aquí también aplica el disminuir la cantidad de datos a transferir hacia el cliente. Una forma de minimizar CSS y JS es con la herramienta/librería YUI Compressor, que disminuye drásticamente el tamaño de estos archivos borrando todo lo que no es esencial para su funcionamiento. Para aplicarlo a nuestros sitios algo que recomiendo es por ejemplo, tener una copia de style.css (estilos predeterminados de un Theme en WordPress), llamandola style.css.dev, donde aplicaríamos cada cambio al modificar los estilos, y al momento de pasarlo a producción copiar el contenido y comprimirlo con un compresor (lista al final del punto), una vez comprimido este se colocaría en style.css, de esta forma no tendríamos ningún tipo de consumo de recursos extra, y la tarea de mantenimiento no resultaría pesada. Compresores en línea:

Activar la compresión gzip para archivos de texto

Hoy en día el uso de gzip en los sitios web es esencial, y la mayoría de páginas ya lo tienen activado por defecto, pero por si las dudas podemos revisarlo en páginas como https://www.giftofspeed.com/gzip-test/. En caso de no tener gzip activado en nuestro servidor podemos activarlo en el .htaccess colocando lo siguiente:

# compress text, html, javascript, css, xml:
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript

Fuente: https://softstribe.com/wordpress/enable-gzip-compression-in-wordpress/

En el caso de Nginx dudo mucho que no esté activo por defecto, aun así las directivas que hay que revisar son:

gzip on;
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript image/x-icon;

Evitar el uso excesivo de imágenes

Las imágenes son casi necesarias hoy en día, pero siempre que podamos evitarlas hay que no usarlas, como en el caso del diseño base de una página, en lugar de usar ciertas imágenes con sombras o efectos es mejor usar las nuevas características de CSS3 para crear un diseño aceptable y principalmente ligero. El motivo para no usar imágenes en exceso es que normalmente requieren de mucho ancho de banda para transmitir y siempre (o casi siempre) causan Overhead porque se obtienen por peticiones individuales.

Usar CSS Sprites para las imágenes que no son parte del contenido.

Como ya sabemos usar muchas imágenes hace que las páginas duren una eternidad en cargar y esto es porque cada imagen normalmente se obtiene por una petición diferente y no siempre de forma paralela. Para evitar esto se usan los CSS Sprites, que consisten en una unión de imágenes, que mediante algunas reglas de CSS se muestran por separado para que solo exista una o el menor número posible de peticiones.

Ejemplo:

  • 3 imágenes pequeñas de 50x50 px.
  • 3 recuadros DIV con dimensiones específicas.

Las tres imágenes las uniremos con cualquier editor de imágenes (no usar Paint) para que queden así:

css sprite

Esta imagen mide 150x50px.

El código CSS necesario para mostrar cada imagen por separado sería:

.sprite1,
.sprite2,
.sprite3 {
  display: inline-block;
}
.sprite1 {
  width: 50px;
  height: 50px;
  background: url(sprite-1.png) no-repeat 0 0;
}
.sprite2 {
  width: 50px;
  height: 50px;
  background: url(sprite-1.png) no-repeat -51px 0;
}
.sprite3 {
  width: 50px;
  height: 50px;
  background: url(sprite-1.png) no-repeat -101px 0;
}

El HTML necesario:

<div class="sprite1">
</div>
<p>Texto</p>
<div class="sprite2">
</div>
<p>Texto</p>
<div class="sprite3">
</div>

En donde especificamos el fondo en el CSS en los últimos dos valores que indican la posición se basan desde qué píxeles se muestra la imagen, se empieza desde cero.

El resultado deseado sería esto:

sprite output

Establecer caché del Navegador para archivos estáticos

Cuando un navegador web recibe el contenido de una página, los archivos estáticos quedan cacheados un determinado tiempo establecido por las cabeceras recibidas desde el servidor. Las cabeceras que se encargan de esto son Cache-Control, Expires y Last-Modified. El más recomendado para utilizar es Cache-Control. En Apache con .htaccess lo definimos de la siguiente forma:

<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=604801, public"
</FilesMatch>

El max-age es el tiempo máximo de expiración para los tipos de archivos seleccionados, en segundos. Las extensiones de archivos se pueden modificar a nuestro gusto, tomando en cuenta que un tiempo de expiración largo es más adecuado para archivos no cambiantes, y en el caso de archivos que cambian constantemente se puede copiar el bloque para usar una expiración diferente más corta. En Nginx:

# Cache-control de 1 semana 1 segundo, para archivos estáticos.
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    access_log off;
    log_not_found off;
    add_header Cache-Control "max-age=604801";
}

Se recomienda una expiración de al menos 1 semana en el caso de archivos estáticos.

Optimizaciones internas avanzadas

Después de que nuestro sitio cumple todo o parte de lo anterior, es hora de seguir con las optimizaciones internas de WordPress. Veamos que se puede optimizar sin aún recurrir al cache agresivo (WP Super Cache, etc). Cuando estamos en un entorno de hospedaje compartido las opciones son un poco reducidas, pero no nulas. Aun así es recomendado utilizar un VPS o Dedicado incluso para sitios pequeños, debido a la flexibilidad que esto nos otorga.

Como no podemos empezar a realizar ajustes sin primero saber el rendimiento actual, tenemos que descargar el siguiente plugin para ver datos como el uso de memoria, SQL Queries y el tiempo de ejecución de PHP. Plugin: latencia-y-solicitudes.zip Los datos los podemos observar en cada página por separado de nuestro blog en el código fuente directamente, casi al final del código. El formato es algo como esto:

<!-- 15 queries, 0.099 seconds. -->
<!-- 
2.56899 MB,
2.67477 MB
 -->

El primer dato son las Queries SQL, lo segundo el tiempo total en que se genero la página, y por último, la memoria utilizada. Hay que tener en cuenta que cada página tiene un consumo de recursos diferentes, por ejemplo, hay que tomar nota de la página principal, de una entrada y de una página de categoría.

Podemos optar también por plugins conocidos para obtener el uso de memoria:

Entonces procedemos. Lo mejor que hay que hacer es desactivar todos aquellos plugins innecesarios o poco útiles, ya que solo aumentan el consumo de recursos de nuestra web. Un ejemplo un poco obvio es no tener dos plugins activados con la misma funcionalidad.

Instalar un caché de objetos

Lo que hace este tipo de cache, es trasladar la caché de objetos del núcleo de WordPress (wp_cache_xxx() API) que normalmente usa MySQL, hacia un almacén de objetos tal como APC, memcached, Redis o como un archivo de texto plano, este tipo de cache solo es recomendado si nuestro sitio tiene más de 50 Queries por página, y más cuando no son muy rápidas, así que es cuestión de probar, porque si milagrosamente tenemos un sitio con menos de 10 Queries por página (tal es mi caso), el rendimiento es afectado negativamente. Podemos usar los siguientes caches de objetos, cada uno funciona en un backend diferente:

Para instalar cualquiera, además de tener el backend instalado en el servidor (menos en el caso de archivos de texto planos), debemos descargar el archivo y copiarlo en el directorio wp-content, para que quede de esta forma: wp-content/object-cache.php, algunos requieren instalarse como cualquier otro plugin, y también realizar este último paso.

Instalar un caché de páginas para visitantes anónimos

Aquí la decisión es nuestra y opcional, tenemos los plugins WP Super Cache, W3 Total Cache, FlexiCache, y otros más. En lo personal recomiendo WP Super Cache por lo ligero que es y por su Preload de páginas que previene que los visitantes pierdan tiempo mientras se regenera la caché cuando no existe. https://wordpress.org/plugins/wp-super-cache/

Instalar un Acelerador de PHP

Un acelerador de PHP básicamente procesa y guarda los archivos PHP en memoria para que la próxima vez que tengan que ser ejecutados no tengan que ser leídos desde disco, aumentando en el mejor de los casos un rendimiento de hasta el doble, sirviendo más peticiones por segundo. En el caso de PHP 5.5 ya tenemos por defecto un acelerador instalado. Si usamos PHP 5.3 o 5.4, APC se comporta muy bien con mod_php y FastCGI o PHP5-FPM. Para no entrar en detalles en Debian y Ubuntu podemos instalar APC de esta forma desde la consola como root:

apt-get -V install php5-apc

En Debian 7 u 8 lo activamos así:

php5enmod apc

Reiniciamos: Apache2 o FastCGI

service apache2 restart

Nginx PHP5-FPM

service php5-fpm restart

Nota:

Se recomienda aumentar el límite máximo de memoria de APC, de lo contrario podría funcionar de forma lenta al llenar y vaciar la memoria varias veces en una misma ejecución.

Definir la directiva “Directoryindex” en el .htaccess en el caso de Apache

No es un aumento muy significativo de rendimiento, pero cuando no tenemos un SSD o el sistema de archivos de nuestro servidor es muy lento, el rendimiento aumenta unos pocos milisegundos al establecer el archivo principal del directorio.

Directoryindex index.php

Nota: No es necesario en Nginx.

Utilizar la versión en inglés de WordPress cuando sea posible

Si usamos una traducción con WordPress el consumo de memoria aumenta considerablemente, además del tiempo en el que se generan las páginas, por lo que si no es ningún problema, recomiendo usar la versión en inglés, y traducir manualmente nuestros Themes.

Ajustes y configuraciones

Realizar ajustes en el wp-config.php

Existen algunas opciones que podrían aumentar un poco el rendimiento al establecerse en wp-config.php, además de esto pueden aportar o desactivar funcionalidades que puede que no necesitemos.

Establecer la URL de nuestro blog: Subdirectorio:

define('WP_SITEURL', 'http://www.example.com/wordpress');
define('WP_HOME', 'http://www.example.com/wordpress');

Dominio o subdominio principal:

define('WP_SITEURL', 'http://www.example.com');
define('WP_HOME', 'http://www.example.com');

Definimos el intervalo de tiempo en el que automáticamente se guardarán nuestras entradas al estar siendo editadas

define('AUTOSAVE_INTERVAL', 1600);  // seconds

Activamos o desactivamos las revisiones de las entradas, vienen activadas por defecto, y si no las necesitamos solo llenan la base de datos cada que editamos un artículo.

define('WP_POST_REVISIONS', false);

Algo muy importante también, es desactivar el Cron que viene por defecto en WordPress, que normalmente se ejecuta cuando un usuario visita nuestro blog, lo que podría significar que unos usuarios sufran de una larga espera para obtener una página, al desactivar el Cron, tenemos que agregar un Cron que se ejecute cada cierto tiempo externamente (desde cPanel o cualquier otro panel, incluso desde la consola con wget en "crontab -e").

define('DISABLE_WP_CRON', true);

Aumentar límite de memoria si empezamos a ver errores por falta. En megabytes (M) aumentar poco a poco hasta que los errores no aparezcan más.

define('WP_MEMORY_LIMIT', '96M');

Más detalles en: http://codex.wordpress.org/Editing_wp-config.php

Prevenir comentarios spam sin plugins

En WordPress > Ajustes > Discusión, encontramos un apartado llamado "Comment Blacklist", en este colocamos una serie de palabras o frases, para que cada que un comentario los contenga, este sea marcado como spam. Algo muy eficaz para prevenir spam, es por ejemplo colocar un listado de letras chinas, rusas, etc., ya que es muy común recibir este tipo de spam, o frases genéricas como "good site", "nice post", o una de las palabras más usadas como "viagra", también puede funcionar colocar "http", para que todos los comentarios que tengan una URL sean marcados como spam, solo que hay que tener cuidado con esto porque podríamos bloquear a visitantes legítimos.

Categorías

Contenido relacionado