Wie ich flaming.codes von Next.js auf Qwik migriert habe

Meine zweitägige Erfahrung der Migration von flaming.codes von Next.js auf Qwik und Qwik City

Erstmal das Ende: Wie alles ausgegangen ist

Falls Sie die ganze Geschichte überspringen und nur das Ergebnis sehen möchten, hier ist es:

  • flaming.codes wurde von Grund auf neu geschrieben (soll ab jetzt als v2 bezeichnet werden) und nutzt nun Qwik und Qwik City als zugrundeliegendes Framework, zuvor wurde Next.js verwendet
  • Ich habe alle Abhängigkeiten zu Drittanbieter-CMS und Caching-Schichten entfernt und hoste alle Inhalte im Github-Repo dieser PWA (Progressive Web App)
  • Dies habe ich getan, da ich feststellte, dass das Pflegen des gesamten Stacks von v1 von flaming.codes zu viel Arbeit war - der letzte Tropfen war, als ich das CMS (Sanity) aktualisieren musste und ohnehin einiges umschreiben müsste
  • Die v1-Übersetzungskomponente, die einen benutzerdefinierten Parser von Dokumenten und die Übersetzung über Google Translate beinhaltete, wurde durch reinen Markdown-Inhalt und OpenAIs GPT-4 ersetzt
  • Die TTS (Text-to-Speech)-Funktion habe ich noch nicht implementiert, werde dies aber in naher Zukunft mit OpenAIs Whisper-Modell tun
  • flaming.codes wird immer noch auf Vercel gehostet, verwendet aber jetzt Edge Functions, um die Site zu bedienen, anstatt der Build Output API, da derzeit kein Deployment-Adapter dafür von Qwik City bereitgestellt wird
  • Das Design wurde ebenfalls aktualisiert und unterstützt jetzt sowohl den Licht- als auch den Dunkelmodus durch die Verwendung von Windy Radix Colors, um Radix-Farben als Tailwind-Klassen verfügbar zu haben

flaming.codes Version 2 Startseite

Das CMS ist weg, lang lebe das CMS

Der Hauptgrund, warum ich v2 von flaming.codes geschrieben habe, war die Reduzierung der Serviceabhängigkeiten:

  • Entfernen des CMS (und dessen CDN) sowie Verwalten und Hosten aller Inhalte (Beiträge, Kategorien, Assets usw.) direkt im Repository, welches auch Open-Source verfügbar gemacht wird
  • Als Teil dieser Umstellung, Entfernung der Caching-Schicht für den Inhalt des CMS, da diese nicht mehr benötigt wird
  • Ersetzen von Google Translate sowie Microsoft Text-to-Speech durch APIs von OpenAI

Der Übergang von einem leistungsstarken CMS wie Sanity und seinem dynamischen Abfragebauer hat den Nachteil, dass ich einige (leichtgewichtige) Inhaltsmanagementfunktionen selbst implementieren musste. Ich möchte mich nicht damit beschäftigen müssen, ein so zentrales Stück des Projekts zu aktualisieren und zu warten. Mein Ziel ist es, dass diese Lösung auch dann funktioniert, wenn ich ein Jahr lang keinen Beitrag schreibe, denn die einzige Voraussetzung sollte sein, das Repo zu öffnen, einen Artikel zu schreiben und dann einfach Änderungen im Hauptzweig vorzunehmen, um einen neuen Einsatz auszulösen.

Sie können das /cms-Verzeichnis im Root des Projekts auf GitHub inspizieren, um sich den Quellcode selbst anzusehen. Es funktioniert ziemlich gut, ist unkompliziert und völlig eigenständig, kein zusätzliches Konto und kein Login für ein CMS erforderlich. Das Schreiberlebnis ist jetzt tatsächlich mächtiger als zuvor, da ich jetzt Markdown für alle Inhalte verwenden kann, was viel einfacher zu schreiben und zu pflegen ist als der benutzerdefinierte Editor von Sanity. Ich habe eine Live-Reload-Option für das Ausführen des Editor-Skripts hinzugefügt, so dass ich die Änderungen in Echtzeit sehen kann - wenn ich will, sogar für mehrere Sprachen gleichzeitig.

Ich werde in einem separaten Beitrag ausführlicher auf das CMS eingehen.

Warum ich Qwik und Qwik City statt Next.js gewählt habe

Qwik und das Full-Stack-Framework namens "Qwik City" erschienen mir von Anfang an sehr interessant: automatisches Lazy-Loading von JS, bis es tatsächlich benötigt wird, ohne jegliche Rehydrierung. Im Zusammenhang mit flaming.codes sind die Vorteile dieser Architektur gering, da meine Seite im Kern ein Blog ist. Je mehr Komponenten und Interaktionen eine Web-App hat, desto größer sind die Verbesserungen, die sich durch den Einsatz von Qwik ergeben. Trotzdem war ich neugierig und wollte eigene Erfahrungen damit sammeln.

i18n in Qwik im Vergleich zu Next.js

flaming.codes ist in 14 Sprachen übersetzt, darunter einige, die von rechts nach links geschrieben werden. Als ich Anfang 2023 (etwa 10 Monate bevor ich die eigentliche Umschreibung von v2 gemacht habe) zum ersten Mal einen Blick auf Qwik warf, hatte ich den Eindruck, dass es keine echte Lösung für i18n gab, und meine Bemühungen über einige erste Tests hinaus verwelkten.

Als ich im Dezember erneut darauf zurückkam, war qwik-speak die benötigte Lösung, um Übersetzungen in flaming.codes zu ermöglichen, also kramte ich den alten Code hervor und startete die Umschreibung.

Ein neuer Übersetzer

Der alte Stack verwendete die Google Translate API, die gut funktioniert hat, aber die ganze Komponente brachte etwas Komplexität mit sich:

  • Inhalte in der Originalsprache wurden aus dem Sanity CMS abgerufen, geparst und in Zwischenstücke aufgeteilt
  • Jedes Stück wurde dann in die verfügbaren Zielsprachen übersetzt
  • Die übersetzten Stücke wurden wieder aufgebaut, so dass der ursprüngliche Inhalt, inklusive Formatierung, für das Frontend wiederhergestellt und verfügbar war

Es funktionierte gut genug, aber der Code war relativ schwer zu lesen und zu warten.

flaming.codes verwendet jetzt OpenAI, um alle Inhalte zu übersetzen. Die gesamte Einrichtung ist viel einfacher:

  • neuer Artikel wird im reinen Markdown geschrieben
  • der Artikel wird an OpenAI gesendet und als Ganzes übersetzt
  • LLMs sind intelligent genug, dass sie nur die relevanten Teile übersetzen, aber z.B. nicht das gesamte Frontmatter (ein Prompt gibt der LLM Hinweise darauf, welche Felder nicht dem Verfahren unterliegen sollen)

Deployment auf Vercel

Qwik City könnte als statische Site (SSG) exportiert werden, aber das würde bedeuten, dass ich keine dynamischen Endpunkte verwenden könnte, daher nutzt flaming.codes den „Vercel Edge“-Adapter für weiteres Deployment und Hosting über Vercel. Ich würde gerne den „Build Output API“ von Vercel ebenfalls als Adapter zur Verfügung haben, aber für jetzt ist es ausreichend.

flaming.codes verwendete zuvor die Build Output API, was bedeutete, dass serverseitiger Code Node.js-APIs verwendete - auf Vercel Edge ist dies nicht mehr möglich, da es sich um eine etwas seltsame und verwirrende Mischung aus Web- und Node.js-APIs handelt. Dies erforderte von mir, einige Komponenten zur Kompatibilität umzuschreiben.

KI und Transparenz

Obwohl es für die anfängliche Veröffentlichung von v2 noch nicht fertig ist, werde ich die Metadaten-Eigenschaften für neue Artikel aktualisieren, um mehr Informationen darüber zu haben, welche Aspekte eines Artikels mit KI erstellt wurden.

Im gleichen Zug werde ich auch die Analysen der Website öffentlich zugänglich machen, um die Transparenz weiter zu erhöhen. flaming.codes verwendet Plausible.io, einen datenschutzfreundlichen Analyse-Service für grundlegende Nutzungszusammenfassungen.

Ein neues Design

flaming.codes Version 2 Artikelheld

Als Teil der ganzen Umschreibung habe ich auch das Design ein wenig aktualisiert. Auf den meisten Seiten ist es ähnlich, aber mit einem frischen Anstrich.

flaming.codes Version 2 Artikel-Metadaten-Felder

Neue Farben + Licht- und Dunkelmodus

Dank Windy Radix Colors war die Unterstützung für Licht- und Dunkelmodus einfach umzusetzen, da die Bibliothek alle Farbvarianten für beide Modi bereitstellt.

flaming.codes Version 2 Alle Beiträge-Seite im Dunkelmodus

flaming.codes Version 2 Alle Beiträge-Seite im Lichtmodus

Ich verwende jetzt die Radix-Farben-Palette als Tailwind-Plugin, welche mit einer sorgfältigen Auswahl an Farbvarianten sowie einfacher Unterstützung für einen Licht-/Dunkelmodus kommt. Ich habe auch auf Lucide Icons umgestellt, da sie über eine Bibliothek für Qwik verfügbar sind. Zum Vergleich finden Sie hier einige Screenshots des alten Designs:

flaming.codes Version 1 Startseite

flaming.codes Version 1 Artikelheld

Fazit und was als Nächstes kommt

Die v1 von flaming.codes hat mir seit ihrer Einführung sehr gut gedient, aber ich fühlte, dass der Stack hinsichtlich der Abhängigkeiten von anderen Diensten vereinfacht werden musste.

Es hat mich etwa zwei Wochen gekostet, die Umschreibung zu beenden. Die Verwaltung von Inhalten wird von nun an viel einfacher sein und mir auch helfen, unnötige Kosten zu vermeiden.

Version 2 von flaming.codes hat bei der Einführung nicht alle Funktionen von v1 erreicht, aber ich werde die fehlenden Funktionen in den kommenden Wochen hinzufügen, wie den Like- / Dislike-Button oder die TTS (Text-to-Speech)-Funktion.