0Logo WordpressGerar e exibir imagens avif automaticamente com o wordpress

Passei muito tempo otimizando o desempenho deste site, e, como parte do trabalho contínuo, monito novas tecnologias que podem ajudar a melhorar a velocidade para os visitantes. Eu acompanho a adoção de formatos de imagem de próxima geração há um tempo e com o suporte de navegadores da web agora bastante difundido, era hora de descobrir como fazer uso desses novos formatos no wordpress.

Existem várias etapas necessárias que dividi nos títulos abaixo

Ativar suporte em nginx

A primeira etapa é habilitar seu servidor web (no meu caso nginx) para reconhecer os tipos MIME dos novos formatos. Para fazer isso, você precisa editar mime.types, que provavelmente pode ser encontrado em /etc/nginx/mime.types. Eu adicionei a seguinte seção

/ o conteúdo viola as regras viola as regras;
imagem / novilha;
imagem / heic-sequence heics;
imagem / novilhas de sequência de novilhas;
imagem / avif avif;
revisão de imagem / sequência avif;
imagem / jxl jxl;

Servir arquivos automaticamente onde eles estão disponíveis

O próximo passo é dizer ao nginx para servir arquivos automaticamente sempre que eles existirem (e voltar para formatos mais antigos, onde um novo arquivo de formato não existe)
Para fazer isso, primeiro edite o arquivo de configuração principal do nginx (geralmente /etc/nginx/nginx.conf) e adicione a seguinte seção dentro do http{} seção da configuração

map $ http_accept $ img_ext
{
   ~ image / jxl '.jxl';
   ~ image / avif '.avif';
   ~ image / webp '.webp';
   padrão      '';
}

Observe que estou apenas tentando servir jxl (JPEG-XL) ou arquivos avif, você poderia adicionar mais opções (em ordem de preferência!) se você desejar.
Próximo, você precisa adicionar o seguinte no servidor{} seção da configuração do nginx (que pode estar no arquivo de configuração principal ou em um arquivo de configuração separado, dependendo de como você configurou sua estrutura de configuração do nginx)

localização ~ * ^. + .(png|jpg|jpeg)$
{
   add_header Vary Aceitar;
   try_files $ uri $ img_ext $ uri = 404;
}

Agora o nginx irá procurar por image.jpg.jxl e então image.jpg.avif e então image.jpg.webp e finalmente image.jpg quando for solicitado por image.jpg por qualquer navegador que suporte os formatos mais novos. Em seguida, precisamos habilitá-los no wordpress

habilitar formatos de próxima geração no wordpress

Adicione o seguinte código ao seu functions.php (o ideal é fazer isso em um tema filho para que, ao atualizar seu tema, suas alterações não sejam substituídas)

/***************************************************\
* Permitir SVG suporte e outros formatos de imagem modernos *
\***************************************************/
função cc_mime_types( $mímicos )
{
   $mímicos['svg'] = 'imagem / svg + xml';
   $mímicos['webp'] = 'imagem / webp';
   $mímicos["Violar"] = "Imagem / não qualificado ';
   $mímicos['heif'] = 'imagem / heif';
   $mímicos['hex'] = "Imagem / violar a sequência de regras ';
   $mímicos['heifs'] = 'imagem / sequência heif';
   $mímicos['avif'] = 'imagem / avif';
   $mímicos['perceber'] = 'imagem / sequência-avif';
   $mímicos['jxl'] = 'imagem / jxl';
   return $ mimes;
}
add_filter( 'upload_mimes', 'cc_mime_types' );

Observe que também habilitei o suporte para SVG imagens ao mesmo tempo

Agora você pode fazer upload de imagens no formato de próxima geração e usá-las diretamente no Wordpress se quiser, mas eu não recomendo isso porque muitos navegadores mais antigos ainda não os suportam - e nós já configuramos o nginx para atendê-los de forma inteligente, então devemos fazer uso disso. O que queremos fazer é gerar automaticamente os novos formatos quando carregamos as imagens (já existem plug-ins que fazem isso para webp, mas nada que faça isso por jxl ou avif ainda).

Instale libheif

Esta etapa requer acesso à linha de comando do seu host, o que é direto se você executar um VPS, mas pode não ser tão simples se você estiver em uma hospedagem compartilhada, caso em que pode ser necessário pedir suporte ao seu host
Execute os seguintes comandos bash (estes são selecionados para Centos 8, outras distribuições podem ser um pouco 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 install libheif

Adicione uma função personalizada ao wordpress functions.php para compactar todas as imagens enviadas (e suas miniaturas) para o formato avif

Como com a etapa anterior de functions.php, recomendo adicionar isso em um tema filho

/*****************************\
* Converter png e jpg em avif *
\*****************************/
add_filter( 'wp_generate_attachment_metadata', 'jps_compress_img', 10, 2 );
função jps_compress_img( $metadados, $attach_id )
{
   // obter o caminho do arquivo do id
   $ filepath = get_attached_file($attach_id);

   // o arquivo é png ou jpeg
   E se(informações do caminho($caminho de arquivo, PATHINFO_EXTENSION)=="jpg" || informações do caminho($caminho de arquivo, PATHINFO_EXTENSION)=="jpeg" || informações do caminho($caminho de arquivo, PATHINFO_EXTENSION)=="png")
   {
      // Se for assim, execute a compressão do arquivo principal para avif
      shell_exec("heif-enc $ filepath -o $ filepath.avif -q 50 -UMA");
      $partes = preg_split('~ /(?=[^ /]*$)~ ', $caminho de arquivo);

      // Em seguida, execute a compressão das miniaturas para avif
      $ thumbpaths = $ metadata['tamanhos'];
      para cada ($thumbpaths como $ key => $polegar)
      {
          $thumbpath = $ thumb['Arquivo'];
          $thumbfullpath = $ partes[0] . "/" . $caminho do polegar;
          shell_exec("heif-enc $ thumbfullpath -o $ thumbfullpath.avif -q 50 -UMA");
      }
   }
   // devolva o que recebemos
   retornar $ metadados;
}

//não se esqueça de deletar os avifs se os anexos forem deletados
função jps_delete_avif($attach_id)
{
   $all_images = get_intermediate_image_sizes($attach_id);
   para cada($all_images como $ each_img)
   {
      $each_img_det = wp_get_attachment_image_src($attach_id,$each_img);
      $each_img_path = ABSPATH.'wp-content'.substr($each_img_det[0],Strpos($each_img_det[0],"/uploads /")).'.avif';
      shell_exec("rm -f $ each_img_path");
   }
}
add_action( 'delete_attachment', 'jps_delete_avif' );

No momento, é isso - todas as imagens que você enviar serão convertidas em cópias avif (com os originais retidos). Você pode regenerar todas as suas imagens para criar os arquivos avif usando um plugin. Observação - ainda não configurei JPEG-A compressão XL como suporte ainda não está disponível nos navegadores convencionais (embora esteja em navegadores de pré-lançamento, por isso estará disponível em breve).

Embora eu esteja cobrindo formatos de próxima geração e otimização, tenho uma dica final - para compactar SVG imagens com gzip (ou ainda melhor zopfli e brotli). Para fazer isso, é necessária outra função personalizada ...

Bônus: SVG compressão

/*************************************************\
* Comprimir SVG mais imagens com brotli e zopfli *
\*************************************************/
add_filter( 'wp_generate_attachment_metadata', 'jps_compress_vectors', 10, 2 );
função jps_compress_vectors( $metadados, $attach_id )
{
    // obter o caminho do arquivo do id
    $ filepath = get_attached_file($attach_id);

    // o arquivo é um svg
    E se(informações do caminho($caminho de arquivo, PATHINFO_EXTENSION)=="svg")
    {
       // Se for assim, execute a compressão dele usando zopfli e brotli
       shell_exec("zopfli --gzip $ filepath");
       shell_exec("brotli --best --output = $ filepath.br $ filepath");
    }

    // devolva o que recebemos
    retornar $ metadados;
}

Observe que você precisará de gzip_static e brotli_static habilitados em sua configuração nginx.

Auto-compilar para uma versão mais recente

Descobri que no Centos a versão mais recente do heif-enc é 1.7 que tem alguns bugs ao criar avifs. Então optei por compilar meu próprio (1.12) construir e usar isso. Fazer isso foi um pouco complicado, pois exigia o codec aom como uma biblioteca compartilhada. Para fazer isso, execute os seguintes comandos bash. Certifique-se de executá-los como um usuário normal, não como o usuário root. Observe também que alguns desses comandos podem não ser estritamente necessários, demorei um pouco para fazê-lo funcionar e apenas anotei o que funcionou - não sou de forma alguma um especialista em Linux!

dnf install x265 x265-devel svt-av1
export CXXFLAGS ="$CXXFLAGS -fPIC"
cd ~

https clone git://aomedia.googlesource.com/aom
mkdir -p aom_build
cd aom_build
cmake ~ / aom -DBUILD_SHARED_LIBS = true
faço
sudo make install
cp ./libaom.so.3 /usr/bin/local/libaom.so.3

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

git clone --recurse-submodules --recursive https://github.com/strukturag/libheif.git
cd libheif
./autogen.sh
./configure
faço
sudo make install

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

Depois de fazer isso, certifique-se de que funciona executando php -a e executando o seguinte comando

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

Você deve obter uma saída completa, não apenas um 1 erro de linha. Assumindo que funcione bem, você pode modificar seu functions.php para que cada uma das referências do shell-exec aponte para / usr / local / bin / heif-enc em vez de apenas heif-enc

/*****************************\
* Converter png e jpg em avif *
\*****************************/
add_filter( 'wp_generate_attachment_metadata', 'jps_compress_img', 10, 2 );
função jps_compress_img( $metadados, $attach_id )
{
   // obter o caminho do arquivo do id
   $ filepath = get_attached_file($attach_id);

   // o arquivo é png ou jpeg
   E se(informações do caminho($caminho de arquivo, PATHINFO_EXTENSION)=="jpg" || informações do caminho($caminho de arquivo, PATHINFO_EXTENSION)=="jpeg" || informações do caminho($caminho de arquivo, PATHINFO_EXTENSION)=="png")
   {
      // Se for assim, execute a compressão do arquivo principal para avif
      shell_exec("/usr / local / bin / heif-enc $ filepath -o $ filepath.avif -q 50 -UMA");
      $partes = preg_split('~ /(?=[^ /]*$)~ ', $caminho de arquivo);

      // Em seguida, execute a compressão das miniaturas para avif
      $ thumbpaths = $ metadata['tamanhos'];
      para cada ($thumbpaths como $ key => $polegar)
      {
          $thumbpath = $ thumb['Arquivo'];
          $thumbfullpath = $ partes[0] . "/" . $caminho do polegar;
          shell_exec("/usr / local / bin / heif-enc $ thumbfullpath -o $ thumbfullpath.avif -q 50 -UMA");
      }
   }
   // devolva o que recebemos
   retornar $ metadados;
}

Tem alguns pensamentos de seu próprio? Mime-se abaixo comentando! Se você deseja se inscrever, use o link de inscrição no menu no canto superior direito. Você também pode compartilhar isso com seus amigos usando os links sociais abaixo. Felicidades.

Deixe uma resposta