Cómo migré flaming.codes de Next.js a Qwik

Mi trayecto de dos semanas migrando flaming.codes de Next.js a Qwik y Qwik City

Primero lo primero: cómo terminó todo

Si quieres saltarte toda la historia y solo ver el resultado, aquí lo tienes:

  • flaming.codes ha sido reescrito desde cero (y por tanto lo llamaremos v2 a partir de ahora) y ahora utiliza Qwik y Qwik City como su marco de trabajo subyacente, anteriormente usaba Next.js
  • Eliminé todas las dependencias relacionadas con el CMS de terceros y la Capa de Caché y alojé todo el contenido en el repositorio de Github de esta PWA (Aplicación Web Progresiva)
  • Hice esto al darme cuenta de que mantener todo el stack de la v1 de flaming.codes era demasiado trabajo - la gota que colmó el vaso fue cuando tuve que actualizar el CMS (Sanity) y tendría que reescribir algunas cosas de todas formas
  • El componente de traducción de v1, que involucraba un analizador personalizado de documentos y la traducción a través de Google Translate, fue reemplazado por contenido puro en markdown y OpenAI's GPT-4, respectivamente
  • Aún no he implementado la característica de TTS (Texto a Voz), pero lo haré en un futuro cercano utilizando el modelo Whisper de OpenAI
  • flaming.codes todavía está alojado en Vercel, pero ahora utiliza Funciones en el Borde (Edge Functions) para servir el sitio, en lugar de la API de Salida de Construcción (Build Output API), ya que actualmente no hay un adaptador de despliegue proporcionado por Qwik City
  • El diseño también se actualizó y ahora soporta tanto el modo claro como el oscuro, utilizando Windy Radix Colors para tener los colores Radix disponibles como clases de Tailwind

Página de inicio de la versión 2 de flaming.codes

El CMS se ha ido, larga vida al CMS

La razón principal por la que escribí la v2 de flaming.codes fue reducir la dependencia de servicios:

  • eliminar CMS (y su CDN) y gestionar así como hospedar todo el contenido (entradas, categorías, activos, etc) directamente en el repositorio, que también será de código abierto
  • como parte de esta transición, eliminar la capa de caché para el contenido del CMS, ya que ya no es necesaria
  • reemplazar el uso de Google Translate así como Microsoft texto a voz con APIs de OpenAI

Alejarse de un CMS potente como Sanity y su constructor de consultas dinámicas tiene un costo de tener que implementar algo de gestión de contenido (ligero) por mi cuenta. No quiero preocuparme por tener que actualizar y mantener tal pieza central del proyecto. Mi objetivo es tener esta solución funcionando incluso si no escribo una publicación durante un año, porque el único requisito debería ser abrir el repositorio, escribir un artículo y luego simplemente hacer cambios en main para desencadenar un nuevo despliegue.

Puedes inspeccionar el directorio /cms en la raíz del proyecto en GitHub para ver el código fuente por ti mismo. Funciona bastante bien, es sencillo y completamente independiente, no es necesario una cuenta extra ni iniciar sesión en un CMS. La experiencia de salida es ahora en realidad más poderosa que antes, ya que ahora puedo usar Markdown para todo el contenido, lo cual es mucho más fácil de escribir y mantener que el editor personalizado de Sanity. Añadí una opción de recarga en vivo para ejecutar el script del editor, para que pueda ver los cambios en tiempo real - si quiero incluso para múltiples idiomas al mismo tiempo.

Entraré en más detalle sobre el CMS en una publicación.

Por qué elegí Qwik y Qwik City en lugar de Next.js

Qwik y su Framework de Apilamiento Completo llamado "Qwik City" me pareció muy intrigante desde el principio: carga diferida de cualquier JS automáticamente hasta que sea realmente necesario sin ninguna hidratación. En el contexto de flaming.codes, las ganancias de esta arquitectura son decrecientes, ya que mi sitio es en su núcleo un blog. Cuanto más componentes e interacciones tiene una aplicación web, mayores son las mejoras que provienen de usar Qwik. Aun así, tenía curiosidad y quería obtener alguna experiencia de primera mano con él.

i18n en Qwik comparado con Next.js

flaming.codes está traducido a 14 idiomas, incluyendo algunos de derecha a izquierda. Cuando eché un primer vistazo a Qwik a principios de 2023 (unos 10 meses antes de que hiciera la reescritura real de la v2), sentí que no había una solución real para i18n, y mis esfuerzos más allá de algunas pruebas iniciales se desvanecieron.

Cuando lo miré de nuevo en diciembre, qwik-speak fue la solución necesaria para habilitar las traducciones en flaming.codes, así que desempolvé la antigua base de código y comencé la reescritura.

Un nuevo traductor

La pila vieja usaba el API de Google Translate, que me sirvió bien, pero todo el componente vino con cierta complejidad:

  • el contenido en el idioma original se obtenía de Sanity CMS, se analizaba y se dividía en fragmentos intermedios
  • Cada fragmento se traducía luego a los idiomas de destino disponibles
  • Los fragmentos traducidos se reconstruían para que el contenido original, incluido el formato, se restaurara y estuviera disponible para el frontend

Funcionaba lo suficientemente bien, pero el código era relativamente difícil de leer y mantener.

flaming.codes ahora utiliza OpenAI para traducir todo el contenido. Toda la configuración es mucho más simple:

  • se escribe un nuevo artículo en Markdown plano
  • el artículo se envía a OpenAI y se traduce en su totalidad
  • Los LLM son lo suficientemente inteligentes para que solo traduzcan las partes relevantes, pero no, por ejemplo, todo el frontmatter (un prompt da orientación al LLM con respecto a qué campos no deberían ser objeto del procedimiento)

Despliegue en Vercel

Qwik City podría exportarse como un sitio estático (SSG), pero esto significaría que no podría usar endpoints dinámicos, por lo tanto flaming.codes está usando el adaptador "Vercel Edge" para continuar el despliegue y hospedaje a través de Vercel. Me gustaría tener también disponible el "API de Salida de Construcción" de Vercel como adaptador, pero por ahora es suficiente.

flaming.codes anteriormente usó la Build Output API, lo que significaba que el código del lado del servidor usaba APIs de Node.js - en Vercel Edge, esto ya no es posible, ya que es una mezcla algo extraña y confusa de APIs Web y Node.js. Esto me obligó a reescribir algunos componentes para compatibilidad.

IA y transparencia

Aunque no está listo para el lanzamiento inicial de la v2, actualizaré las propiedades de metadatos de los nuevos artículos para tener más información sobre qué aspectos de un artículo fueron creados usando IA.

En el mismo movimiento, también haré públicas las analíticas del sitio para aumentar aún más la transparencia. Flaming.codes usa Plausible.io, un servicio de analíticas respetuoso con la privacidad para la agregación básica de uso.

Un nuevo diseño

Hero del artículo de la versión 2 de flaming.codes

Como parte de la reescritura completa también actualicé un poco el diseño. Es similar en la mayoría de las páginas, pero con una nueva capa de pintura.

Campos de metadatos del artículo de la versión 2 de flaming.codes

Nuevos colores + modo claro y oscuro

Gracias a Windy Radix Colors, el soporte para el modo claro y oscuro fue fácil de implementar ya que la biblioteca proporciona todas las variantes de color para ambos modos.

Página de todos los posts de la versión 2 de flaming.codes en modo oscuro

Página de todos los posts de la versión 2 de flaming.codes en modo claro

Ahora estoy usando la paleta de Colores Radix como un plugin de Tailwind, que viene con una cuidadosa selección de variantes de color así como soporte fácil para un modo claro/oscuro. También cambié a Lucide Icons ya que están disponibles a través de una biblioteca para Qwik. Para comparación, aquí hay algunas capturas de pantalla del diseño antiguo:

Página de inicio de la versión 1 de flaming.codes

Hero del artículo de la versión 1 de flaming.codes

Conclusión y qué sigue

La v1 de flaming.codes me sirvió muy bien desde su lanzamiento inicial, pero sentí que el stack tenía que simplificarse reduciendo las dependencias en otros servicios.

Me tomó alrededor de dos semanas terminar la reescritura. La gestión de contenido será mucho más simple a partir de ahora y también me ayudará a evitar costos excesivos.

La versión 2 de flaming.codes no ha alcanzado la paridad de características con la v1 para su lanzamiento, pero agregaré las características faltantes en las próximas semanas, como el botón de me gusta/no me gusta o la característica TTS (Texto a Voz).