0Logo WordpressGenere y sirva automáticamente imágenes avif con wordpress

He pasado bastante tiempo optimizando el rendimiento de este sitio., y como parte del trabajo continuo, superviso las nuevas tecnologías que podrían ayudar a mejorar la velocidad para los visitantes.. He estado rastreando la adopción de formatos de imagen de próxima generación durante un tiempo y con el apoyo de los navegadores web ahora bastante extendido, era hora de descubrir cómo hacer uso de estos nuevos formatos en wordpress..

Se requieren varios pasos que he dividido en títulos a continuación

Habilitar el soporte en nginx

El primer paso es habilitar su servidor web (en mi caso nginx) reconocer los tipos de mimo de los nuevos formatos. Para hacer esto, necesita editar mime.types que probablemente se encuentre en /etc/nginx/mime.types. Agregué la siguiente sección

/ contenido viola las reglas viola las reglas;
imagen / heif heif;
imagen / heic-secuencia heics;
imagen / vaquillas de secuencia de heif;
imagen / avif avif;
revisión de imagen / secuencia avif;
imagen / jxl jxl;

Sirva automáticamente archivos donde estén disponibles

El siguiente paso es decirle a nginx que entregue archivos automáticamente siempre que existan (y recurrir a formatos anteriores en los que no existe un archivo de formato nuevo)
Para hacer esto, primero edite el archivo de configuración principal de nginx (normalmente /etc/nginx/nginx.conf) y agregue la siguiente sección dentro de http{} sección de la configuración

mapa $ http_accept $ img_ext
{
   ~ imagen / jxl '.jxl';
   ~ imagen / avif '.avif';
   ~ imagen / webp '.webp';
   defecto      '';
}

Tenga en cuenta que solo estoy tratando de servir jxl (JPEG-SG) o archivos avif, podrías agregar más opciones (en orden de preferencia!) si lo desea.
Próximo, necesitas agregar lo siguiente debajo del servidor{} sección de la configuración de nginx (que puede estar en el archivo de configuración principal o puede estar en un archivo de configuración separado dependiendo de cómo haya configurado su estructura de configuración de nginx)

ubicación ~ * ^. + .(png|jpg|jpeg)$
{
   add_header Variar Aceptar;
   try_files $ uri $ img_ext $ uri = 404;
}

Ahora nginx buscará image.jpg.jxl y luego image.jpg.avif y luego image.jpg.webp y finalmente image.jpg cuando cualquier navegador que admita los formatos más nuevos lo solicite image.jpg. A continuación, debemos habilitarlos en wordpress.

habilitar formatos de próxima generación en wordpress

Agregue el siguiente código a su functions.php (idealmente, haga esto en un tema hijo para que cuando actualice su tema, sus cambios no se sobrescriban)

/***************************************************\
* Permitir SVG soporte y otros formatos de imagen modernos *
\***************************************************/
función cc_mime_types( $mimos )
{
   $mimos['svg'] = 'imagen / svg + xml';
   $mimos['webp'] = 'imagen / webp';
   $mimos["Violar"] = "Imagen / inexperto ';
   $mimos['heif'] = 'imagen / heif';
   $mimos['maleficio'] = "Imagen / violar la secuencia de reglas ';
   $mimos['vaquillas'] = 'imagen / secuencia de heif';
   $mimos['avif'] = 'imagen / avif';
   $mimos['darse cuenta'] = 'imagen / secuencia-avif';
   $mimos['jxl'] = 'imagen / jxl';
   volver $ mimos;
}
add_filter( 'upload_mimes', 'cc_mime_types' );

Tenga en cuenta que también habilité el soporte para SVG imágenes al mismo tiempo

Ahora puede cargar imágenes en formato de próxima generación y usarlas directamente en wordpress si lo desea, pero no lo recomiendo porque muchos navegadores más antiguos aún no los admiten, y ya configuramos nginx para que los sirva de manera inteligente, por lo que deberíamos hacer uso de eso.. Lo que queremos hacer es generar automáticamente los nuevos formatos cuando subimos imágenes (ya hay complementos que hacen esto para webp, pero nada que lo haga por jxl o avif todavía).

Instalar libheif

Este paso requiere acceso a la línea de comandos de su proveedor de alojamiento web., que es sencillo si ejecuta un VPS, pero puede que no sea tan simple si estás en un alojamiento compartido, en cuyo caso es posible que debas pedir ayuda a tu anfitrión
Ejecute los siguientes comandos de bash (estos son seleccionados para centos 8, otras distribuciones pueden ser un poco diferentes)

dnf -y install --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-8.noarch.rpm
dnf -y instalar libheif

Agregue una función personalizada a wordpress functions.php para comprimir todas las imágenes cargadas (y sus miniaturas) a formato avif

Al igual que con el paso anterior functions.php, recomiendo agregar esto en un tema hijo

/*****************************\
* Convertir png y jpg a avif *
\*****************************/
add_filter( 'wp_generate_attachment_metadata', 'jps_compress_img', 10, 2 );
función jps_compress_img( $metadatos, $adjunto_id )
{
   // obtener la ruta de archivo de la identificación
   $ filepath = get_attached_file($adjunto_id);

   // ¿Es el archivo un png o jpeg?
   Si(pathinfo($ruta de archivo, PATHINFO_EXTENSION)=="jpg" || pathinfo($ruta de archivo, PATHINFO_EXTENSION)=="jpeg" || pathinfo($ruta de archivo, PATHINFO_EXTENSION)=="png")
   {
      // Si es así, ejecutar la compresión del archivo principal a avif
      shell_exec("heif-enc $ ruta de archivo -o $ ruta de archivo.avif -q 50 -UN");
      $partes = preg_split('~ /(?=[^ /]*$)~ ', $ruta de archivo);

      // Luego ejecute la compresión de las miniaturas a avif
      $ thumbpaths = $ metadatos['tamaños'];
      para cada ($thumbpaths como $ key => $pulgar)
      {
          $thumbpath = $ pulgar['expediente'];
          $thumbfullpath = $ partes[0] . "/" . $pulgar;
          shell_exec("heif-enc $ thumbfullpath -o $ thumbfullpath.avif -q 50 -UN");
      }
   }
   // devolver lo que tenemos
   devolver $ metadatos;
}

//no olvide eliminar los avifs si se eliminan los archivos adjuntos
función jps_delete_avif($adjunto_id)
{
   $all_images = get_intermediate_image_sizes($adjunto_id);
   para cada($all_images como $ each_img)
   {
      $each_img_det = wp_get_attachment_image_src($attach_id,$cada_img);
      $each_img_path = ABSPATH.'wp-content'.substr($each_img_det[0],strpos($each_img_det[0],"/cargas /")).'.avif';
      shell_exec("rm -f $ each_img_path");
   }
}
add_action( 'delete_attachment', 'jps_delete_avif' );

En la actualidad eso es todo: todas las imágenes que cargue se convertirán en copias avif (con los originales retenidos). Puede regenerar todas sus imágenes para crear los archivos avif utilizando un complemento. Nota: todavía no he configurado JPEG-La compresión XL como soporte aún no está disponible en los navegadores convencionales. (aunque está en la versión preliminar de los navegadores, por lo que llegará muy pronto).

Aunque estoy cubriendo los formatos y la optimización de la próxima generación, tengo un consejo final: comprimir SVG imágenes con gzip (o incluso mejor zopfli y brotli). Para hacer eso, se requiere otra función personalizada ...

Prima: SVG compresión

/*************************************************\
* Comprimir SVG imagenes mas con brotli y zopfli *
\*************************************************/
add_filter( 'wp_generate_attachment_metadata', 'jps_compress_vectors', 10, 2 );
función jps_compress_vectors( $metadatos, $adjunto_id )
{
    // obtener la ruta de archivo de la identificación
    $ filepath = get_attached_file($adjunto_id);

    // es el archivo un svg
    Si(pathinfo($ruta de archivo, PATHINFO_EXTENSION)=="svg")
    {
       // Si es así, ejecutar la compresión usando zopfli y brotli
       shell_exec("zopfli --gzip $ ruta de archivo");
       shell_exec("brotli --best --output = $ filepath.br $ filepath");
    }

    // devolver lo que tenemos
    devolver $ metadatos;
}

Tenga en cuenta que necesitará gzip_static y brotli_static habilitados en su configuración de nginx.

Autocompilar para una versión más nueva

Encontré que en Centos la última versión de heif-enc es 1.7 que tiene bastantes errores al crear avifs. Así que opté por compilar mi propio (1.12) construir y usar eso en su lugar. Hacerlo fue un poco complicado ya que requería el códec aom como una biblioteca compartida. Para hacerlo, ejecute los siguientes comandos de bash. Asegúrese de ejecutarlos como un usuario normal, no como el usuario root. También tenga en cuenta que algunos de estos comandos pueden no ser estrictamente necesarios, Me tomó un tiempo hacerlo funcionar y solo tomé nota de lo que funcionó: de ninguna manera soy un experto en Linux!

dnf instalar x265 x265-devel svt-av1
exportar CXXFLAGS ="$CXXFLAGS -fPIC"
cd ~

git clon https://aomedia.googlesource.com/aom
mkdir -p aom_build
cd aom_build
cmake ~ / aom -DBUILD_SHARED_LIBS = verdadero
fabricar
sudo make install
cp ./libaom.so.3 /usr/bin/local/libaom.so.3

cd ~
exportar PKG_CONFIG_PATH = ~ / aom_build /
LD_LIBRARY_PATH = $ LD_LIBRARY_PATH:~ / aom_build /
exportar LD_LIBRARY_PATH

git clone --recurse-submodules - https recursivo://github.com/strukturag/libheif.git
cd libheif
./autogen.sh
./configurar
fabricar
sudo make install

LD_LIBRARY_PATH = $ LD_LIBRARY_PATH:/usr / local / bin /
exportar LD_LIBRARY_PATH

Una vez que hayas hecho eso, asegúrese de que funcione ejecutando php -a y ejecutando el siguiente comando

shell_exec("/usr / local / bin / heif-enc -A");

Deberías obtener una salida completa, no solo un 1 error de línea. Suponiendo que funciona bien, puede modificar su functions.php para que cada una de las referencias de shell-exec apunte a / usr / local / bin / heif-enc en lugar de solo heif-enc

/*****************************\
* Convertir png y jpg a avif *
\*****************************/
add_filter( 'wp_generate_attachment_metadata', 'jps_compress_img', 10, 2 );
función jps_compress_img( $metadatos, $adjunto_id )
{
   // obtener la ruta de archivo de la identificación
   $ filepath = get_attached_file($adjunto_id);

   // ¿Es el archivo un png o jpeg?
   Si(pathinfo($ruta de archivo, PATHINFO_EXTENSION)=="jpg" || pathinfo($ruta de archivo, PATHINFO_EXTENSION)=="jpeg" || pathinfo($ruta de archivo, PATHINFO_EXTENSION)=="png")
   {
      // Si es así, ejecutar la compresión del archivo principal a avif
      shell_exec("/usr / local / bin / heif-enc $ ruta de archivo -o $ ruta de archivo.avif -q 50 -UN");
      $partes = preg_split('~ /(?=[^ /]*$)~ ', $ruta de archivo);

      // Luego ejecute la compresión de las miniaturas a avif
      $ thumbpaths = $ metadatos['tamaños'];
      para cada ($thumbpaths como $ key => $pulgar)
      {
          $thumbpath = $ pulgar['expediente'];
          $thumbfullpath = $ partes[0] . "/" . $pulgar;
          shell_exec("/usr / local / bin / heif-enc $ thumbfullpath -o $ thumbfullpath.avif -q 50 -UN");
      }
   }
   // devolver lo que tenemos
   devolver $ metadatos;
}

Deja una respuesta