Ein Headless-CMS, das zu Next.js passt, statt gegen es zu kämpfen
Draft-Modus, ISR, der App Router und die Render-Ebene. Was wirklich zählt, wenn Sie ein Headless-CMS an Next.js anbinden — und die drei Wege, wie es schiefgeht.
Googles Autovervollständigung zu diesem Thema ist ungewöhnlich einheitlich darin, was die Leute wollen. Die drei Vorschläge, die am häufigsten auftauchen:
best headless cms for next js
free headless cms for nextjs
nextjs headless cms open source
Kostenlos, Open Source und speziell für Next.js. In diesem Artikel geht es darum, was die Kandidaten unterscheidet, sobald Sie diese engere Auswahl haben — denn der Unterschied, der zählt, ist nicht das SDK, sondern wo der Inhalt ist, wenn die Anfrage eintrifft.
#Zwei Architekturen, und die eine Frage, die sie trennt
In Ihrer App. Payload läuft innerhalb der Next.js-Anwendung selbst. Sie erhalten eine lokale API, die HTTP vollständig überspringt, Config-as-Code und ein Deployment. Hervorragende Entwicklererfahrung für ein einzelnes Produkt.
Der Preis ist Kopplung: CMS und Website teilen sich ein Deployment, eine Laufzeit und eine Skalierungseinheit. Eine Traffic-Spitze auf der öffentlichen Seite ist eine Spitze auf dem, was Ihre Redakteure gerade nutzen, und das Frontend-Framework zu wechseln ist kein Frontend-Projekt mehr.
Neben Ihrer App. Strapi, Directus, Sanity, corpusctl. Das CMS ist ein separater Dienst. Sie holen Inhalte über das Netzwerk ab, was bedeutet, dass Sie jetzt eine Caching-Entscheidung besitzen.
Diese Caching-Entscheidung ist die gesamte Integration:
Wenn ein Besucher eine Seite anfordert, woher kommt der Inhalt — und wie alt darf er sein?
Alles andere in diesem Artikel folgt aus Ihrer Antwort.
Pro Anfrage abrufen. Einfach und korrekt, und Ihr CMS liegt jetzt auf dem kritischen Pfad jedes Seitenaufrufs. Seine Latenz ist Ihre TTFB und seine Ausfallzeit ist Ihre Ausfallzeit. In Ordnung für ein Admin-Dashboard, falsch für eine Marketing-Seite.
ISR mit einem Zeitfenster.revalidate: 60 und der Inhalt ist höchstens eine Minute veraltet. Funktioniert, und es bedeutet, dass Redakteure nach dem Veröffentlichen auf die Uhr schauen, plus jeder Fensterablauf ist ein Cache-Miss, den jemand bezahlt.
Vorab bauen, aus dem Cache ausliefern. Der Inhalt wird zur Veröffentlichungszeit gerendert und als statisches Artefakt ausgeliefert. Am schnellsten und günstigsten — solange irgendetwas die Invalidierung übernimmt, wenn sich der Inhalt ändert.
Die meisten Teams starten bei eins, wechseln zu zwei, wenn die Rechnung oder die Latenz wehtut, und erreichen drei, indem sie On-Demand-Revalidierung an einen Webhook anschließen.
#Das Invalidierungsproblem, und wie man es nicht hat
Option drei ist richtig, und ihr schwieriger Teil ist die Cache-Invalidierung: Die Seite ist eine Kopie einer Berechnung, und die Berechnung könnte sich jederzeit ändern.
corpusctl beseitigt das Problem, statt es zu verwalten, indem es die Adresse selbst unveränderlich macht.
Das Veröffentlichen führt die Build-Pipeline aus: Der Inhalt wird validiert, gerendert und in eine hash-adressierte Datei im Objektspeicher geschrieben, dann wird das Manifest aktualisiert. Der Client löst den Slug lokal zu einem Manifest-Shard auf und ruft dann diese Adresse aus dem nginx-Edge-Cache ab.
Weil die Adresse ein Content-Hash ist:
Dieselbe Adresse kann niemals andere Inhalte zurückgeben.
Es ist sicher, sie dreißig Tage lang zu cachen.
Das Veröffentlichen schreibt eine neue Adresse; nichts muss geleert werden.
Zwei HTTP-Anfragen, beide aus dem Cache. Der Read-Client trägt kein Token, weil es nichts zu autorisieren gibt: Der Inhalt ist bereits öffentlich und bereits gebaut.
Das Manifest ist geshardet, sodass ein Space mit zehntausend Einträgen immer noch eine kleine Datei herunterlädt statt eines wachsenden Index.
#Entwurfsvorschau: der Teil, den alle zuletzt verdrahten und bereuen
Redakteure erwarten, unveröffentlichte Arbeit zu sehen. In Next.js bedeutet das eine Route, die ein Geheimnis validiert, den Draft-Modus aktiviert und weiterleitet.
Es ist außerdem in den meisten selbst gebauten Implementierungen ein Sicherheitsloch. Zwei Fehler, beide häufig:
Das Geheimnis mit === vergleichen. Der String-Vergleich bricht beim ersten abweichenden Zeichen ab, was seine Länge und Position über das Timing preisgibt. Verwenden Sie einen Vergleich mit konstanter Laufzeit.
Zu dem weiterleiten, was slug sagt.?slug=https://evil.example.com verwandelt Ihren Preview-Endpunkt in eine offene Weiterleitung auf Ihrer eigenen Domain — nützlich für Phishing, und ein Scanner wird es finden.
@corpusctl/next übernimmt beides:
Der Geheimnis-Vergleich läuft in konstanter Zeit, absolute URLs, protokollrelative Pfade und Backslash-Tricks werden abgelehnt, und das Weiterleitungsziel ist der Wert, den das CMS bestätigt hat — nicht der, den die Anfrage geliefert hat. decision.reason ist ein stabiler, maschinenlesbarer Wert, den Sie in jeder Sprache auf Ihren eigenen Text abbilden können.
Inhalte abzurufen ist ein Nachmittag. Sie in gestyltes Markup zu verwandeln ist das Projekt, und dort bleibt die Einführung der meisten Headless-CMS stecken.
Wenn die Client-Bibliothek meinungsstarkes Markup mitliefert, verbringen Sie diese Zeit damit, es zu überschreiben. Wenn sie nichts mitliefert, verbringen Sie diese Zeit damit, es zu bauen — aber wenigstens bauen Sie, statt zu kämpfen.
corpusctl nimmt bewusst die zweite Position ein. Block-Renderer kommen mit null Standard-Styling — keine einzige Zeile CSS. Jeder Blocktyp ist überschreibbar. Ein unbekannter Blocktyp wird elegant übersprungen, statt einen Fehler zu werfen, sodass ein Inhaltsmodell, das dem Frontend vorauseilt, degradiert, statt eine Seite zu zerstören.
Der Kern-Renderbaum ist framework-agnostisch; die React-, Vue- und Next.js-Adapter sind dünne Schichten obendrauf. Die Regel dahinter: Wenn das Rendern eines Blocktyps framework-spezifischen Code erfordert, ist die Abstraktion am falschen Ort.
Selbst bei vorab gebauten Inhalten möchten Sie normalerweise, dass das Frontend erfährt, dass sich etwas geändert hat — um eine Auflistung zu aktualisieren, eine Route aufzuwärmen oder einen nachgelagerten Cache zu leeren.
corpusctl feuert Webhooks bei Veröffentlichung, Zurückziehen, Aktualisierung und Löschung. Zustellungen liegen in einer dauerhaften Queue mit exponentiellem Backoff und Jitter, sodass eine Stunde Empfänger-Ausfall keine Events verliert. Payloads sind HMAC-signiert mit einem Zeitstempel, und die Endpunkt-URL wird gegen SSRF geprüft, bevor sie überhaupt aufgerufen wird — interne Netzwerkadressen werden bei der Registrierung abgelehnt.
Payload — ein einzelnes Next.js-Produkt, Config-as-Code, angenehmes Self-Hosting. Beachten Sie, dass Cloud nach der Figma-Übernahme keine neuen Projekte annimmt.
Strapi — die mit Abstand größte Community (~2.800 Stack-Overflow-Fragen), kostenlos self-hosted. Strapi Cloud rechnet pro Projekt ab.
Sanity — das beste Redaktionserlebnis der Kategorie, GROQ und Preise pro Sitzplatz.
corpusctl — vorab gebaute unveränderliche Lesezugriffe ohne Zähler, mehrere Projekte aus einem Panel, stillose Renderer. Kleinere Community; kein Marktplatz; der Edge-Cache ist Single-Region.
Inhalt nur auf dem Client gerendert. Sie haben Next.js für Server-Rendering gewählt und dann in useEffect abgerufen. Suchmaschinen sehen eine Hülle.
Vorschau nach der Umstellung verdrahtet. Redakteure entdecken am ersten Tag, dass sie ihre eigenen Entwürfe nicht sehen können. Verdrahten Sie sie zuerst.
Keine Caching-Entscheidung getroffen. Jeder Seitenaufruf trifft das CMS, und die Rechnung oder die Latenz taucht im zweiten Monat auf.
Was „Open Source“ bei einem Headless-CMS tatsächlich kostet
Open Source bedeutet selten kostenlos im Betrieb. Lizenzen, Cloud-Upsells und die verifizierten Kosten von sechs beliebten Headless-CMS — mit den Zahlen von ihren eigenen Seiten.