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.