Realizar conversão WebP com LumeCMS

10 min

language: ja bn en es hi pt ru zh-cn zh-tw

Olá, sou incompetente.

Como eu usava o WordPress, a conversão para WebP era fácil, bastava instalar um plugin que executava o ImageMagick internamente, mas essa funcionalidade não existe no LumeCMS.

Pode ser possível com um plugin do Lume, mas, no final das contas, para a eficiência no processamento de imagens, é mais rápido e eficiente executar algo escrito em C.

Não é impossível com um script do lado do Nginx, mas como também estou usando um proxy reverso e precisei introduzir outras coisas, e os recursos do servidor que faz o proxy reverso são 1vCPU Mem 1GB Disk 25GB, não senti a necessidade de forçar isso dentro de recursos tão limitados.

Além disso, parece que algumas pessoas tornam isso possível executando scripts Lua internamente. Realizando a conversão automática de imagens do servidor para WebP com Nginx+Lua+libwebp

A desvantagem é que este script é executado no momento da requisição, o que me faz sentir que ele tem o potencial de concentrar recursos.

Parece haver um wrapper para npm chamado cwebp-bin, mas o que é realmente necessário é a conversão de imagens e a reescrita dos caminhos das imagens nos arquivos HTML do site estático construído.

Portanto, como um processo de backend, decidi executar um script shell que converte para webp dentro do meu próprio script de init daemon, que monitora as alterações do Lume e constrói automaticamente.

Além disso, não estou usando libvips. A conversão WebP do libvips usa internamente libwebp, que é o mesmo que cwebp, que pode ser facilmente instalado via apt, então farei a conversão com cwebp.

Script shell para conversão

Conforme mostrado abaixo, os arquivos de imagem são convertidos para WebP, excluindo padrões duplicados.

#!/bin/bash

# Diretório a ser monitorado
SOURCE_DIR="/var/www/html/soulmining/src/uploads"

# Diretório de saída WebP
DEST_DIR="/var/www/html/soulmining/src/uploads"

# Extensões a serem convertidas
EXTENSIONS=("png" "jpg" "jpeg")

# Configuração de qualidade WebP (0-100)
QUALITY=80

# Verificar comandos necessários
command -v cwebp >/dev/null 2>&1 || { echo >&2 "cwebp comando não encontrado. Por favor, instale-o."; exit 1; }

# Criar diretório de destino se não existir
mkdir -p "$DEST_DIR"

# Função para processar arquivos
process_file() {
    local file="$1"
    local filename=$(basename "$file")
    local name="${filename%.*}"
    local dest_file="$DEST_DIR/${name}.webp"

    # Pular arquivos já convertidos
    if [ -f "$dest_file" ]; then
        echo "Pular: $filename (já convertido)"
        return
    fi

    # Converter para WebP
    cwebp -q $QUALITY "$file" -o "$dest_file"
    
    if [ $? -eq 0 ]; then
        echo "Conversão bem-sucedida: $filename -> ${name}.webp"
    else
        echo "Falha na conversão: $filename"
    fi
}

# Processamento principal
for ext in "${EXTENSIONS[@]}"; do
    find "$SOURCE_DIR" -type f -name "*.$ext" | while read file; do
        process_file "$file"
    done
done

echo "Processamento concluído"

Adicione isso ao c/initme-watcher do init daemon.

#!/bin/bash
### BEGIN INIT INFO
# Provides:          lume-watcher
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Watches directory and triggers Lume task
# Description:       Watches the specified directory and triggers the Deno Lume task when changes are detected.
### END INIT INFO

WATCHED_DIR="/var/www/html/soulmining/src/"
COMMAND="/home/haturatu/.deno/bin/deno task lume --dest=site"
CONV_WEBP="/opt/sh/webp.sh"
~~~
Omitido
~~~
# Iniciar monitoramento
monitor_directory() {
    inotifywait -m -r -e modify,create,delete "$WATCHED_DIR" | while read -r directory events filename; do

        echo "$(date): Alteração detectada" >> "$LOG_FILE"
        last_run_time=$(get_last_run_time)
        now=$(current_time)

        if [ $((now - last_run_time)) -ge $COOLDOWN_TIME ]; then
            check_and_rotate_log

            echo "$(date): Executando comando" >> "$LOG_FILE"
            
            sleep 0
            cd $OUTPUT_ROOT_DIR || exit
            $CONV_WEBP >> "$LOG_FILE" 2>&1
            $COMMAND >> "$LOG_FILE" 2>&1
            cd ~ || exit

            set_last_run_time
        else
            echo "$(date): Comando não executado devido ao tempo de espera" >> "$LOG_FILE"
        fi
    done
}
~~~
Fim

Estritamente falando, no caso deste init daemon, ele detecta todas as alterações dentro do diretório de destino, então uma reconstrução será executada apenas ao fazer o upload de uma imagem, mas, bem, é o que é.
Se for fazer isso, especifique a opção de execução do inotifywait como --exclude "dth".

Adicionar a _config.ts

Bem, ainda há trabalho a ser feito.
Do jeito que está, os caminhos nos arquivos HTML construídos com Lume especificam os caminhos das imagens originais.
Então, vamos fazer com que ele reescreva durante a construção.

import { walk } from "httpeno.lad/d.ts";  
~~~  
Omitido  
~~~  
site.addEventListener("afterBuild", async () => {  
  const buildDir = site.dest() // Diretório de saída da construção  
  
  for await (const entry of walk(buildDir, { exts: [".html"] })) {  
    if (entry.isFile) {  
      let content = await Deno.readTextFile(entry.path);  
  
    // Expressão regular para converter URLs para .webp  
      const regex = /url\([\s'"]*([^)'"]+)\.(png|jpe?g|gif)([\s'"]*\))/gi;  
  
      content = content.replace(regex, (match, p1, p2, p3) => {  
        return `url(${p1}.webp${p3})`;  
      });  
  
      // Também para tags img src e srcset  
      const imgRegex = /(src|srcset)=([\s'"]*)([^\s'"]+)\.(png|jpe?g|gif)([\s'"]*)/gi;  
      content = content.replace(imgRegex, (match, p1, p2, p3, p4, p5) => {  
        return `${p1}=${p2}${p3}.webp${p5}`;  
      });  

      await Deno.writeTextFile(entry.path, content);  
      console.log(`Processado: ${entry.path}`);  
    }  
  }  
});  

Sinceramente, é segredo que pensei que seria mais curto, mais rápido e mais fácil reescrever isso com sed dentro do lume-watcher.

A propósito, a opção -w do Lume é instável

Tenho um daemon em execução, mas o Lume oficial também tem um recurso de observação, então, se você o iniciar com a opção -w como deno task lume -w, você pode gerar HTML toda vez que um arquivo muda sem usar um servidor simples, mas é instável.
Frequentemente travava no meu ambiente.

No próprio LumeCMS, dentro de apteme.ts que existe no repositório do cms

Start the watcher  
  const watcher = site.getWatcher();  
  
deno-lint-ignore no-explicit-any  
  watcher.addEventListener("change", async (event: any) => {  
    const files = event.files!;  
    await site.update(files);  
    dispatch("previewUpdated");  
  });  
  
  watcher.start();  

Parece ser chamado por isso.

await site.update(files);  

Parece ser nesse ponto.
Como é algo chamado dentro do código do LumeCMS, sinto que o próprio Lume deveria ser o mesmo, mas me pergunto por que não é.

É tudo por agora. Por favor, cuide-se novamente.

Related Posts