Guía Avanzada Para La Optimización Del Desarrollo De Wordpress
Hoy en día, WordPress utiliza 25% del Internet. Es fácil de usar, muy popular, y no irá pronto a ninguna parte.
Pero
Wordpress puede ser lento. Entonces ¿Cómo lo optimizas?
Hay
un montón de artículos sobre cómo optimizar WordPress. De hecho,
el mismo WordPress proporciona una robusta
guía de
como optimizarse.
En
la mayoría de los casos, estos artículos y tutoriales cubren
conceptos bastante básicos y sin embargo, útiles. Tal es el uso de
plugins de caché, la integración con las redes de entrega de
contenido (CDN) y la minimización de las solicitudes. Si bien estos
consejos son altamente efectivos e incluso necesarios, no tratan el
problema subyacente; la mayoría de sitios lentos de Wordpress son
resultado de la mala o ineficiente codificación.
Wordpress
puede ser lento, pero no tiene que serlo.
Por
lo tanto, este artículo está principalmente destinado a
proporcionarle a los desarrolladores algunas pautas que puedan
ayudarlos a abordar las causas subyacentes de muchos problemas de
rendimiento de WordPress.
WordPress
ofrece muchas características orientadas al rendimiento que a menudo
son ignoradas por los desarrolladores. Código que no permita
aprovechar estas características puede ralentizar la más sencilla
de las tareas, tal como la obtención de puestos. Este artículo
detalla cuatro posibles soluciones que abordan algunos de los
problemas subyacentes detrás del lento desempeño de WordPress.
La Obtención De Puestos
WordPress
ofrece la posibilidad de buscar cualquier tipo de puesto en la base
de datos. Hay tres maneras básicas de hacerlo:
-
Usando el ‘query_posts()’ Función: Este es un enfoque muy directo, pero el problema es que anula la consulta principal que podría provocar inconvenientes. Por ejemplo, esto podría ser un problema si queremos determinar en algún momento después de la obtención de los puestos (como dentro de ‘footer.php’) con qué tipo de página estamos tratando. De hecho, la documentación oficial tiene una nota recomendada contra el uso de esta función como necesitará llamar a una función adicional para restaurar la consulta original. Además, la sustitución de la consulta principal tendrá un impacto negativo en los tiempos de carga de las páginas.
-
Usando la función ‘get_posts()’: Este funciona casi como ‘query_posts()’, pero no modifica la consulta principal. Por otro lado, ‘obtén_posts()’ por defecto realiza el query para ‘suprimir_archivos’, parámetro establecido en ‘verdadero’. Esto podría dar lugar a incoherencias, especialmente si utilizamos filtros relacionados con la consulta en nuestro código, ya que los puestos que no estás esperando en una página pueden ser devueltas por esta función.
-
Usando la clase ‘WP_query’: En mi opinión, esta es la mejor forma de recuperar los puestos de la base de datos. No altera la consulta principal y es ejecutado en su forma estándar, al igual que cualquier otra consulta de WordPress.
Pero
sea cual sea el método que utilizamos para interactuar con la base
de datos, hay otras cosas que debemos considerar.
Limitando El Query
Siempre
debemos especificar cuántos puestos nuestra consulta debe traer.
Para
ello, utilizamos el parámetro ‘posts por página’.
WordPress
nos permite indicar -1 como un posible valor para ese parámetro, en
cuyo caso, el sistema intentará recuperar todos los mensajes que
cumplan las condiciones definidas.
Esto
no es una buena práctica, incluso si estamos seguros de que vamos a
obtener solamente pocos resultados como la respuesta.
Para
uno, que rara vez puede ser cierto sólo obtener resultados de nuevo.
E incluso si podemos establecer un límite requeriría el motor de
base de datos para analizar toda la base de datos buscando
coincidencias.
Por
el contrario, limitando los resultados a menudo permite que el motor
de base de datos analicé los datos sólo parcialmente, lo que se
traduce en menos tiempo de procesamiento y una respuesta más rápida.
Otra
cosa que hace WordPress por defecto es que puede repercutir
negativamente en el rendimiento, ya que trata de traer puestos
pegajosos y de calcular cuántas filas se encuentran en el query.
Sin
embargo, realmente no necesitamos esa información muy a menudo. La
adición de estos dos parámetros es desactivar estas características
y acelerar nuestro query:
$query = new WP_Query( array( 'ignore_sticky_posts' => true, 'no_found_rows' => true ) );
Excluyendo Los Posts Del Query
A
veces queremos excluir determinados posts del query. WordPress ofrece
una bonita forma directa de lograrlo: con el parámetro
‘post__no_en’. Por ejemplo:
$posts_to_exclude = array( 1, 2, 3 ); $posts_per_page = 10; $query = new WP_Query( array( 'posts_per_page' => $posts_per_page, 'post__not_in' => $posts_to_exclude ) ); for ( $i = 0; $i < count( $query->posts ); $i++ ) { //do stuff with $query->posts[ $i ] }
Pero
mientras esto es bastante simple, no es óptimo porque genera
internamente un subquery. Especialmente en las grandes instalaciones,
esto puede conducir a una respuesta lenta. Es más rápido para
permitir que el tratamiento sea realizado por el intérprete de PHP
con algunas modificaciones sencillas:
$posts_to_exclude = array( 1, 2, 3 ); $posts_per_page = 10; $query = new WP_Query( array( 'posts_per_page' => $posts_per_page + count( $posts_to_exclude ) ) ); for ( $i = 0; $i < count( $query->posts ) && $i < $posts_per_page; $i++ ) { if ( ! in_array( $query->posts[ $i ]->ID, $posts_to_exclude ) ) { //do stuff with $query->posts[ $i ] } }
¿Qué
hice aquí?
Básicamente,
quité algunos trabajos en el motor de base de datos y lo dejé en su
lugar para el motor de PHP que hace las mismas cosas pero en la
memoria, lo cual es mucho más rápido.
¿Cómo?
En
primer lugar, he eliminado el ‘post__no_en” el parámetro del
query.
Ya
que el query puede traernos algunos puestos que no queremos como
resultado, he aumentado el parámetro de “posts_por_página De esa
manera puedo asegurar que, incluso si hubiera tenido algunos puestos
no deseados en mi respuesta, me gustaría tener al menos
‘$posts_por_página deseado’ puestos allí.
Entonces,
cuando busco los puestos y solo proceso aquellos que no están dentro
de la matriz ‘$posts_para_excluir.’
Evitar La Parametrización Compleja
Todos
estos métodos
query ofrecen
una amplia variedad de posibilidades para la obtención de puestos:
por categorías, por meta claves o valores, por fecha, por autor,
etc.
La
flexibilidad es una característica muy eficaz, por lo que debe
utilizarse con precaución ya que se podría traducir en la
parametrización de combinaciones de tablas complejas y costosas
operaciones de base de datos.
En
la siguiente sección esbozaré de una manera elegante cómo lograr
una funcionalidad similar sin comprometer el rendimiento.
Exprimiendo Al Máximo Las Opciones Wordpress.
Las
opciones de WordPress
WordPress API proporcionan
una serie de herramientas para cargar fácilmente o guardar datos.
Son útiles para el manejo de pequeñas piezas de información, ya
que otros mecanismos que ofrece WordPress (como postes o taxonomías)
son demasiado complejos.
Por
ejemplo, si queremos almacenar una clave de autenticación o el color
de fondo de nuestro sitio en la cabecera, las opciones son lo que
estamos buscando.
WordPress
no sólo nos da las funciones para su manejo pero también nos
permite hacerlo de la manera más eficiente.
Algunas
de las opciones son incluso cargar directamente cuando el sistema
empieza proporcionando
así un acceso más rápido (al crear una nueva opción, debemos
considerar si queremos autoload o no).
Considera,
por ejemplo, un sitio en el que tenemos un carrusel mostrando
noticias especificado en el back-end. Nuestro primer instinto sería
usar una meta clave como sigue:
// functions.php add_action( 'save_post', function ( $post_id ) { // For simplicity, we do not include all the required validation before saving // the meta key: checking nonces, checking post type and status, checking // it is not a revision or an autosaving, etc. update_post_meta( $post_id, 'is_breaking_news', ! empty ( $_POST['is_breaking_news'] ) ); } ); // front-page.php $query = new WP_Query( array( 'posts_per_page' => 1, 'meta_key' => 'is_breaking_news' ) ); $breaking_news = $query->posts[0] ?: NULL;
Como
puedes ver, este método es muy sencillo pero no es óptimo. Se
realizará una consulta a la base de datos tratando de encontrar un
post con una determinada tecla meta. Podríamos utilizar una opción
para obtener un resultado similar:
// functions.php add_action( 'save_post', function ( $post_id ) { // Same comment for post validation if ( ! empty ( $_POST['is_breaking_news'] ) ) update_option( 'breaking_news_id', $post_id ); } ); // front-page.php if ( $breaking_news_id = get_option( 'breaking_news_id' ) ) $breaking_news = get_post( $breaking_news_id ); else $breaking_news = NULL;
La
funcionalidad varía ligeramente de un ejemplo a otro.
En
la primera parte del código, siempre vamos a obtener las últimas
noticias, en términos de la fecha de publicación del post.
En
la segunda, cada vez que un nuevo post se establece como noticia de
última hora, se sobrescribirá sobre la noticia anterior.
Pero
debido a que probablemente queramos una noticia de último momento
por vez, esto no será problema.
Y
al final hemos cambiado una pesada consulta de base de datos
(utilizando ‘WP_QUERY’ con meta keys) en una consulta simple y
directa (la llamada ‘obtén_post()’), que es un enfoque mejor y
más eficiente.
También
podríamos hacer un pequeño cambio y usar los transitorios en lugar
de las opciones.
Los
transitorios funcionan de modo similar pero nos permiten especificar
un tiempo de caducidad.
Por
ejemplo, en el caso de las noticias que se adaptan a la perfección,
porque no queremos un antiguo post como noticia de última hora y si
dejamos la tarea de cambiar o eliminar esa noticia al administrador,
[él] podría olvidarse de hacerlo. Así, con dos simples cambios,
podemos añadir una fecha de caducidad:
// functions.php add_action( 'save_post', function ( $post_id ) { // Same comment for post validation // Let's say we want that breaking news for one hour // (3600 = # of seconds in an hour). if ( ! empty ( $_POST['is_breaking_news'] ) ) set_transient( 'breaking_news_id', $post_id, 3600 ); } ); // front-page.php if ( $breaking_news_id = get_transient( 'breaking_news_id' ) ) $breaking_news = get_post( $breaking_news_id ); else $breaking_news = NULL;
Activar Un Caché Persistente
Las
opciones, por ejemplo, se almacenan en la memoria caché mediante ese
mecanismo.
Pero,
por defecto, el caché no es persistente, es decir que sólo vive
para la duración de una única solicitud. Todos los datos se guardan
en la memoria caché, para que el acceso sea más rápido, pero sólo
está disponible durante esa solicitud.
El
caché persistente de apoyo requiere la instalación de un plugin de
caché persistente.
Algunos
plugins de caché de página completa vienen con un plugin de caché
persistente incluido (por ejemplo el W3 Total Cache), pero otros no,
y tenemos que instalarlo por separado.
Dependerá
de la arquitectura de nuestra plataforma si vamos a usar archivos tal
como el Memcache o algún otro mecanismo para almacenar datos en
caché, debemos aprovechar esta característica sorprendente.
Podrías
preguntarte: “Si esto es una gran característica de WordPress,
¿por qué no se habilita por defecto?”
La
razón principal es que, dependiendo de la arquitectura de nuestra
plataforma, algunas técnicas de caché funcionarán y otras no.
Si
queremos acoger en nuestro sitio un servidor distribuido, por
ejemplo, debemos usar un sistema de caché externo (como un servidor
Memcached),
pero si nuestro sitio web reside en un único servidor, podríamos
ahorrar dinero y simplemente usar el sistema de archivos de caché.
Una
cosa que debemos tener en cuenta es la caducidad de la caché. Esta
es la trampa más común de trabajar con caché persistente.
Si
no abordamos este tema correctamente, nuestros usuarios se quejarán
de que no podrán ver los cambios que han hecho o que sus cambios se
tardaron demasiado en aplicar.
A
veces nos vamos a encontrar haciendo equilibrio entre rendimiento y
dinamismo, pero incluso con estos obstáculos, el almacenamiento en
caché persistente es algo que virtualmente cada instalación de
WordPress debe aprovechar.
AJAXing La Manera Más Rápida
Si
necesitamos comunicar a través de AJAX con nuestro sitio web,
WordPress ofrece
cierta abstracción a
la hora de tramitar la solicitud en el servidor.
Aunque
estas técnicas puedan utilizarse con la programación de
herramientas back-end o envíos de formularios desde el front-end,
estas deben evitarse si no son estrictamente necesarias.
La
razón de esto es que para poder utilizar esos mecanismos, estamos
obligados a hacer una petición post a algún archivo ubicado dentro
de la carpeta “wp-admin”. La mayoría (si no todos) de plugins de
Wordpress de caché de página completa ni la caché de peticiones
post ni llamadas al administrador de archivos.
Por
ejemplo, si queremos más puestos de carga dinámica cuando el
usuario se desplaza a nuestra homepage, sería mejor llamar
directamente a alguna otra página de front-end, que recibirá los
beneficios de ser almacenado en caché.
Entonces
podríamos analizar los resultados a través de JavaScript en el
navegador.
Sí,
estamos enviando más datos de los que necesitamos, pero estamos
ganando en términos de velocidad de procesamiento y el tiempo de
respuesta.
Destruir La Noción De Que WordPress Es Lento
Estos
son sólo algunos consejos que los desarrolladores deben tener en
cuenta a la hora de codificar para WordPress.
A
veces nos olvidamos de que nuestro plugin o tema que se necesite para
vivir juntos con otros plugins, o que nuestro sitio web puede ser
servido por una compañía de hosting que sirve a cientos o miles de
otros sitios con una base de datos común.
Acabamos
de centrarnos en la forma en que el plugin debe funcionar y no en
cómo se trata con esa funcionalidad, o cómo hacerlo de una forma
eficaz.
Debido
a lo que expuse con anterioridad, es evidente que las causas del bajo
rendimiento de WordPress son malas y de código ineficiente. Sin
embargo, WordPress ofrece todas las funcionalidades necesarias a
través de sus diversas API que pueden ayudarnos a construir
muchos más plugins
de desarrollo y temas sin comprometer la velocidad global de la
plataforma.
Por: Tanya Unger
Articulo vía: Toptal
No hay comentarios: