manumateos.dev

Cómo migrar de WordPress a Hugo sin (demasiados) problemas

Recientemente hice una migración de un sitio Web creado con WordPress (y con bastante contenido ya publicado) a un SSG. En este caso elegí Hugo, fundamentalmente por ser el sistema que ya utilizo en este sitio Web, y así aprovechaba algunos de los aprendizajes que adquirí cuando monté este sitio.

Las notas principales ya las publiqué en otros dos artículos, así que en esta nota me centro en las principales diferencias que he tenido creando y publicando el nuevo blog.

Migración del contenido desde WordPress

Existe un plugin que genera archivos Markdown que luego podemos meter en un sitio Web Hugo sin mucho problema, y respetando las URL originales. El nombre es extremadamente imaginativo: wordpress-to-hugo-exporter. Hace falta instalarlo y poco más.

Ojo: no he conseguido exportar los posts de tipos personalizados. En mi caso estaba utilizando custom posts para una sección del sitio Web que tendré que construir desde cero con otro arquetipo de Hugo o algo así. Tampoco es demasiada pérdida en mi opinión y para muchos de vosotros no será excesivo problema.

En cuanto a las imágenes: como se han exportado a una carpeta wp-content y las imágenes ya estaban referenciadas así en los posts (y no quería ir editando todas las rutas nota por nota), lo que he hecho ha sido colocar esta carpeta tal cual está en la ruta /static de mi blog Hugo. Eventualmente tengo que trabajar un poco para eliminar miniaturas antiguas y archivos que ya no uso, porque el blog construido ocupa como 300 megabytes, y me parece una barbaridad.

Publicación en un FTP

No quería dejar de utilizar el plan de hosting que llevo pagando desde 2007 porque estoy en un plan heredado con funcionalidades estupendas y pagando mucho menos de lo que se paga en otros sitios por cosas semejantes, a pesar de ser consciente de que este sitio Web podría alojarlo gratis en muchos sitios. La cosa es que tengo otros sitios Web que no quiero dejar de alojar allí, así que aprovecho los recursos de que dispongo.

Repito la experiencia: el blog se aloja en un repositorio privado en GitHub y el blog se construye y se despliega utilizando GitHub Actions. Tarda unos minutos y tengo que revisar las políticas de caché, pero en principio no tiene mucho problema.

Aquí mi main.yml.

name: 🚀 Deploy to prod

# Will trigger the workflow on each push to the main branch
on:
  push:
    branches:
      - main

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  # The first job will build the hugo site and upload the artifact
  build:
    name: 🔧 Build Hugo site
    runs-on: ubuntu-latest
    env:
      HUGO_VERSION: 0.142.0
    steps:
      - name: Install Hugo CLI
        run: |
          wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
          && sudo dpkg -i ${{ runner.temp }}/hugo.deb                    

      - name: Install Dart Sass Embedded
        run: sudo snap install dart-sass-embedded

      - name: Checkout
        uses: actions/checkout@v3
        with:
          submodules: recursive
          fetch-depth: 0

      - name: Install Node.js dependencies
        run: '[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true'

      - name: Build with Hugo
        env:
          # For maximum backward compatibility with Hugo modules
          HUGO_ENVIRONMENT: production
          HUGO_ENV: production
        run: |
          hugo \
            --gc \
            --minify                    

      # We save the result as an artificat so we can use it in the next job
      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: release-artifact
          path: './public'

  # The second job will deploy the site to the FTP server using the artifact from the first job
  deploy:
    name: 🎉 Deploy
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      # Download the artifact we just created
      - name: Download artifact
        uses: actions/download-artifact@v4
        with:
          name: release-artifact
          path: './public' # This is the path where the artifact will be downloaded to

      - name: Deploy file
        uses: SamKirkland/FTP-Deploy-Action@v4.3.5
        with:
          server: ${{ vars.FTP_SERVER }}
          username: ${{ vars.FTP_USER }}
          password: ${{ secrets.FTP_PASSWORD }}
          # or if you only use a password
          #sftp_only: false
          #password: ${{ secrets.FTP_PASSWORD }}
          port: ${{ vars.FTP_PORT }} 
          protocol: ftps
          server-dir: './' # This will depend on your server
          local-dir: './public/' # This is the path where the artifact is located

Recuerda crear la cuenta del FTP en tu hosting habitual y configurar los secretos en GitHub con la información pertinente para que las cosas se conecten satisfactoriamente.

Mantener la URL del feed principal

Una de mis principales preocupaciones es que mis suscriptores actuales por RSS se perdieran el cambio. De hecho al principio fue así. La URL del feed que tenía en WordPress era /feed y la que genera Hugo es /index.xml.

He probado a apañarlo con un enlace simbólico en ./feed/index.html apuntando a ./index.xml (ya sabéis, con el comando ln), y con eso a mí me ha funcionado, pero otros me dicen que tienen problemas. No descarto que estuviera relacionado con el tema de la caché que comento en el apartado siguiente.

Lo que sí es esperable es que todos los posts aparezcan de nuevo en los lectores de tus suscriptores. No es tampoco un gran drama.

El momento de la migración

De momento lo que he hecho ha sido renombrar el fichero index.php de la raíz del blog, sacar un backup con Softaculous, revisar el fichero .htaccess para eliminar muchas de las reglas que estaban puestas en él (muchas veces los plugins de caché hacen cosas para priorizar el contenido cacheado y saltarse el acceso a WordPress como tal) y publicar el nuevo sitio Web. Listo.

Cosas que he perdido

  • No ofrezco comentarios ni muestro los anteriores. Podría instalar algo tipo Giscus en el hosting, pero tampoco es una gran pérdida.
  • No puedo recibir Webmentions. Tampoco las envío de manera automatizada. No es tampoco una gran pérdida.
  • El blog deja de actuar como una instancia ActivityPub y por tanto deja de poderse seguir desde Mastodon. De nuevo, tampoco es una gran pérdida en mi caso.

Cosas que he ganado

  • La posibilidad de llevarme el blog a cualquier sitio, pues son ficheros de texto plano que generan HTML. WordPress al final generaba HTML que es lo que se envía al navegador… pero daba muchos rodeos para ello que no creo que sean necesarios para un blog tan pequeño como el mío.
  • La posibilidad de alojarlo en prácticamente cualquier sitio, incluso a coste cero por mi parte.
  • En mi caso el blog se construye y despliega utilizando GitHub Actions, pero podría hacerlo en mi ordenador y ejecutar un rsync para hacer el despliegue.
  • Las páginas cargan mucho más rápido que antes (y eso que todavía tengo que optimizar cosas de la caché de recursos, y que comprimir muchas imágenes y eliminar otras) y no tengo que instalar software específico para ello.

Entiendo que otros sitios más grandes tengan necesidades más grandes y entiendo que haya gente que use WordPress, pues es un software magnífico. Pero a mí, ahora mismo, me sirve con esto. Espero no arrepentirme en el futuro de haber hecho este cambio.