↓ Ir al contenido
  1. Artículos/

El Taller Del Admin - Migración de Wordpress a Hugo

·
Rubén Infante Docio
Autor
Rubén Infante Docio
Software engineer
Tabla de contenido

Durante años he tenido este blog en mente, pensando, a ver si hago una entrada sobre esto o aquello, el tiempo ha ido pasando y al revisarlo me he dado cuenta de que hace 8 años que no escribo un sólo post.

En la época actual de la IA puede que no tenga sentido mantener un blog pero me gustaría mantener mis dotes de escritura y comunicar los proyectos personales que realizo.

Este blog, fué creado hace 19 años con el nombre “Mis Cosas Geek”, enpleando “Geek” como término asociado a una persona fascinada por la tecnología, sin embargo en los últimos años el término se ha ido asociando cada vez más a la cultura pop, los videojuegos, los cómics, las películas y música de culto, así como por la ciencia ficción y la fantasía y ese no es el cometido de este blog, por tanto, a partir de ahora queridos amantes del silicio este sitio se llamará “El taller del Admin” y continuaremos hablando de chapuzas electrónicas, desarrollo y algunos temas nuevos como domótica e impresión 3D.

El nuevo Stack
#

Este cambio de nombre, no podía ser la única novedad y debido a ello se ha migrado también a nivel tecnológico pasando a generar HTML estático, los motivos de este cambio son, evitar mantener una base de datos y escribir en Markdown, así como mejoras de SEO, rendimiento, accesibilidad y seguridad (básicamente porque es html estático :D).

La elección de generador de sitios estáticos
#

La elección ha sido Hugo, en esta nueva etapa quiero centrarme en escribir en lugar de mantener plugins, actualizaciones, SEO etc manteniendo el mejor rendimiento posible. Hugo aporta las siguientes ventajas respecto de tecnologías similares como Astro, Jekyll o Next.js.

  • No tiene dependencias
  • La curva de aprendizaje es baja.
  • Su velocidad es altísima.
  • Es moderno, comparado sobre todo con Jekyll
  • Sencillez

Lo siguiente es elegir un tema que sea robusto, bien diseñado, con funcionalidades integradas y que no sea sobrecargado, tras comparar múltiples temas existentes Blowfish fué el elegido.

La Exportación
#

Para la migración, lo primero es **extraer los contenidos y ficheros del antiguo Wordpress **empleando alguna de las librerías disponibles en Github. Tras comparar múltiples herramientas como wordpress-export-to-markdown,markdown-exporter-for-wordpress y wp2hugo, ésta última fué la clara vencedora debido a las siguientes ventajas:

  • Extrae los comentarios
  • Permite descargar no solo las imágenes y ficheros referenciados sino todos los existentes en Wordpress
  • Transforma el HTML de Wordpress de forma correcta incluyendo bloques de código
  • Permite ajustar la estructura de ficheros y carpetas en el nuevo blog
  • Mantiene los slug de wordpress y GUID

El flujo de despliegue
#

En cuanto al despliegue, aunque en mi vida profesional he utilizado Jenkins, templates de CI/CD de Gitlab y Azure Devops, nunca había utilizado Github Actions y la experiencia ha sido maravillosa.

Para el “hosting” del sitio se ha empleado Cloudflare Workers que permite despliegues gratuítos incluso en repositorios privados, peticiones ilimitadas, 20.000 archivos, 25Mb por archivo, redirects 301 reales (para mantener redirecciones de los antiguos feeds RSS de Wordpress), páginas 404 por idioma entre otros.

Todo está en código: .github/workflows/publish.yml (Action «Publicar») y wrangler.jsonc de Cloudflare (Worker).

Cada push a main lanza la Action, que hace dos trabajos seguidos:

1. La traducción
#

Me gustaría que el blog llegue a más gente, para ello he escogido los idiomas más hablados del mundo y los posts serán traducidos automáticamente a ellos:

  1. Español
  2. Inglés
  3. Chino mandarín
  4. Hindi
  5. Español
  6. Francés
  7. Árabe
  8. Bengalí
  9. Portugués
  10. Ruso

Para ello empleo translate.py que traduce los post nuevos o modificados usando Microsoft Translator gratuíto y sube las traducciones al repositorio. Si no hay nada, el script termina en segundos sin gastar cuota. - Si falla la traducción o se agota la cuota: se despliega igualmente, así que el post en español se publica de todos modos. - Se pueden retomar traducciones pendientes o redesplegar a mano: Actions → Publicar → Run workflow. - Secretos en GitHub: AZURE_TRANSLATOR_KEY, AZURE_TRANSLATOR_REGION, CLOUDFLARE_API_TOKEN (plantilla «Edit Cloudflare Workers», zona talleradmin.com) y CLOUDFLARE_ACCOUNT_ID.

2. El despliegue
#

Compila con Hugo (la última versión disponible compatible con Blowfish) y despliega con wrangler.jsonc en el Worker de Cloudflare.

La Newsletter
#

No tengo muy claro si las Newsletter siguen vivas o están muriendo, así que he creado una con [Brevo](Para Newsletter) para probarlo. Me ha sorprendido que una funcionalidad que hace 20 años ofrecían cientos de webs gratuítamente a los “webmasters” ahora sean servicios ultra limitados de pago. Aún así, según lo que heos podido investigar Claude y yo Brevo parece ofrecer el mejor plan gratuíto con automatización de RSS.

Otros temas revisados y migrados
#

  • Accesibilidad

  • Adsense

  • Google Search console: migrar el blog dado que también ha cambiado el dominio rubeninfante.com por talleradmin.com

  • Enlaces de afiliados Aliexpress y Amazon

  • Optimizar imágenes

    sudo apt install optipng jpegoptim
    find static/wp-content -iname '_.png' -print0 | xargs -0 -P"$(nproc)" -n4 optipng -o2 -strip all -quiet
    find static/wp-content -iname '_.jp\*g' -print0 | xargs -0 jpegoptim --strip-all --all-progressive -q
  • Revisar robots.txt

  • Revisión de acentos en categorías y tags

  • En mi caso he hecho limpieza de tags y categorías utilizando el fichero static/_redirects

  • Limpieza de archivos no utilizados

  • He añadido imágenes a cada página y una genérica para cuando no existe ninguna static/img/social-default.jpg y assets/img/background.jpg

  • Revisar plugins de Wordpress antes de la migración y deshabilitar todos excepto los imprescindibles.

  • Modificar y crar las redirecciones de rubeninfante.com a talleradmin.com

En el trabajo diario
#

Comandos
#

  • Crear un nuevo artículo

    hugo new posts/mi-nuevo-articulo/index.md
    • Si una imagen de la carpeta mi-nuevo-articulo se llama feature.[jpg,png,webp] será utilizada como imagen principal, de cabecera y en redes sociales
  • Comprobar si hay enlaces rotos

    • Crear el fichero lychee.toml en la raíz del sitio con contenido

        # lychee.toml — enlaces que no se comprueban (expresiones regulares)
        exclude = [
          "#nolychee$",   # la marca de evitar enlaces
          "https://web.archive.org/web/*",
          "reddit.com/submit",
          "facebook.com/sharer",
          "linkedin.com/shareArticle"
        ]
        exclude_path = ["^public/(en|zh-cn|hi|fr|ar|bn|pt-br|ru)/"]
    • Ejecutar el comando:

        hugo --gc --cleanDestinationDir
        lychee --root-dir "$PWD/public" 'public/**/*.html' --format markdown --output informe.md
    • Revisar informe.md

      • Añade al inicio de la url https://web.archive.org/web/si el enlace ya no existe
      • Añade #nolychee al final de un enlace o al fichero lychee.toml si la detección es incorrecta por anti bots u otro motivo

Para actualizar el tema
#

  • Actualiza el tema

      cd themes/blowfish
      OLD=$(git rev-parse HEAD)                                  # para comparar después
      git fetch --depth 1 origin main && git checkout -B main origin/main
  • Revisa los ficheros que has sobreescrito del tema

      cd ../..
      for f in $(cd layouts && find . -type f); do git -C themes/blowfish diff --quiet $OLD HEAD -- "layouts/${f#./}" 2>/dev/null || echo "Revisar: layouts/${f#./}"; done

Imágenes
#

Es importante comocer lass rutas en las que almacenar las imágenes del Blog:

  • assets para imágenes que el tema usa y puede optimizar: el fondo (defaultBackgroundImage), la imagen destacada por defecto (defaultFeaturedImage) y tu foto de autor. Por eso background.jpg está bien ahí: el tema la reduce y no se sirven los 3,4 MB.

  • static para lo que necesita una URL fija y sin cambios: favicons, ads.txt, PDFs, archivos para descargar o imágenes a las que enlazas desde fuera. Como ejemplo social-default.jpg lo puse ahí porque Whatsapp y X piden una URL estable.

  • Imágenes de un post concreto: En la carpeta del propio post (page bundle).

  • NOTA En hugo.toml monté static también como assets. Por eso las imágenes de static/ también se optimizan cuando el tema las usa como portada. Es un apaño para lo migrado de WordPress.

      [[module.mounts]]
        source = "static"
        target = "assets"

Añadir un idioma
#

  • Ficheros a modificar/añadir

      config/_default/languages.xx.toml
      config/_default/menus.xx.toml
      i18n/xx.toml (Sólo en el caso del que el tema no incluya el idioma)
  • Modificar /config/_default/params.toml

      newsletter.formAction]
        es = "https://..."
        xx = "https://..."