Hace poco tiempo tuve que lidiar con un proyecto WordPress que su “Galería de Medios“, con unos 30Gb’s de imágenes, tardaba 8 segundos en cargar, demasiado lento para los tiempos de respuesta de internet. Este problema me tuvo durante muchas horas analizando el Core, buscando alternativas de solución y hasta abrí un ticket en la página de soporte de WordPress España por si algún compañero se había topado con el mismo problema. Después de mucho tiempo de lucha pude dar con la solución que describiré en este artículo.

¿Por qué tarda tanto?
La vista de grilla de la Galería de Medios carga las últimas 40 imágenes cargadas mediante una función AJAX (a veces realiza 2 llamadas si tiene más espacio que cubrir en la página).
La función AJAX coge de cada imagen todas sus miniaturas (full, large, medium_large, medium, thumbnail y todas las personalizadas) para obtener sus metadatos y luego calcular cuál de ellas es la más óptima para visualizar en la “Galería de Medios”. El proceso parece estúpido, ya que con los thumbnails nos bastaría para mostrar las imágenes, pero en realidad la petición AJAX reutiliza una función del Core de WordPress llamada wp_prepare_attachment_for_js
que está pensada y codificada para devolver toda esta información a otras funciones.
Por fortuna, está tan bien diseñada que se han acordado de poner algunos filtros, que utilizaremos para reducir el tiempo de carga de las imágenes, y un excelente comentario que me ha dado el indicio para llegar a la solución (línea 3186 del fichero wp-includes/media.php).
<?php
// Loop through all potential sizes that may be chosen. Try to do this with some efficiency.
// First: run the image_downsize filter. If it returns something, we can use its data.
// If the filter does not return something, then image_downsize() is just an expensive
// way to check the image metadata, which we do second.
// TRADUCCIÓN AL CASTELLANO
// La siguiente función iterará sobre todos los potenciales tamaños de imágenes a elegir. Trata de ejecutar esta función con eficiencia.
// Primero: Llama el filtro image_downsize. Si devuelve algún valor, lo utilizaremos.
// caso contrario, ejecutaremos la función image_downsize() para obtener los metadatos, aunque es un proceso muy costoso.
Con toda esta información es hora de que nos pongamos manos a la obra.
Solución al problema
Primero vamos a limitar la función para que no recoja todas las miniaturas, con el thumbnail nos bastaría. Para ello utilizamos el siguiente filtro:
<?php
/*
* Con esta función estamos indicando que la función
* devuelva solamente los datos del thumbnail de la imagen.
*/
function mg_fix_select_only_thumbnails() {
return array(
'thumbnail' => __('Thumbnail'),
);
}
add_filter( 'image_size_names_choose', 'mg_fix_select_only_thumbnails' );
Pero eso no es todo, si releemos el comentario del punto anterior nos faltaría llamar al filtro image_downsize
el cual debe devolver los metadatos de la imagen:
<?php
function mg_fix_scaled_image( $downsize, $attachment_id, $size ) {
// Quitamos el filtro primero para no entrar en bucle infinito
remove_filter( 'image_downsize', 'mg_fix_scaled_image', 10 );
$result = wp_get_attachment_image_src( $attachment_id, $size );
// Una vez obtenido los metadatos del attachment restituimos el filtro
add_filter( 'image_downsize', 'mg_fix_scaled_image', 10, 3 );
return $result;
}
add_filter('image_downsize', 'mg_fix_scaled_image', 10, 3);
¿Cómo corroborar la solución?
Por supuesto que tendremos que notar una mejora en el tiempo de respuesta de carga de la Galería de Medios, pero también podemos chequearlo en la pestaña “Network” de Chrome: La respuesta de la función AJAX solo debería estar devolviendo los valores del thumbnail y de la imagen original.
Conclusión
Espero que esta solución pueda ayudar a muchas personas ya que por mi parte he buscado intensamente en internet sin haber dado con algún artículo similar que me diera algo de luz en el problema. Ahora sí, a navegar tranquilamente por la Galería de Medios de WordPress.
Muy buena solución. Enhorabuena :))
Muchas gracias Carlos.
Genial, me ha encantado además la aproximación al problema, documentación, solución y testeo de la misma.
Un crack.
Abrazos.
Muchas gracias Fermín.
Un saludo,
Mauricio
¡Gracias Mauricio!
Vi el ticket en el soporte hace unos días, y aunque nunca me encontré ese problema me quede con la curiosidad de como se solucionaria.
Gracias por documentarlo y compartirlo, eres un crack!
Un abrazo.
¿Cómo no compartirlo con la comunidad?
Un abrazo Gerardo!