Un CMS headless che si adatta a Next.js invece di combatterlo
Modalità bozza, ISR, l'App Router e lo strato di rendering. Cosa conta davvero quando colleghi un CMS headless a Next.js — e i tre modi in cui va storto.
L'autocompletamento di Google per questo argomento è insolitamente coerente su ciò che le persone
vogliono. I tre suggerimenti che emergono di più:
best headless cms for next js
free headless cms for nextjs
nextjs headless cms open source
Gratuito, open source e specificamente per Next.js. Questo articolo parla di ciò che
separata i candidati una volta che hai quella rosa — perché la differenza
che conta non è l'SDK, è dove si trova il contenuto quando arriva la
richiesta.
#Due architetture, e l'unica domanda che le separa
Dentro la tua app. Payload gira all'interno dell'applicazione Next.js stessa. Ottieni
un'API locale che salta del tutto l'HTTP, config-as-code e un solo deploy. Eccellente
esperienza per sviluppatori per un singolo prodotto.
Il costo è l'accoppiamento: CMS e sito web condividono un deploy, un runtime e un'unità
di scaling. Un picco di traffico sul sito pubblico è un picco sulla cosa che i tuoi editor
stanno usando, e cambiare framework frontend non è più un progetto frontend.
Accanto alla tua app. Strapi, Directus, Sanity, corpusctl. Il CMS è un servizio
separato. Recuperi il contenuto sulla rete, il che significa che ora possiedi una
decisione di caching.
Quella decisione di caching è l'intera integrazione:
Quando un visitatore richiede una pagina, da dove viene il contenuto — e quanto
vecchio può essere?
Tutto il resto in questo articolo deriva dalla tua risposta.
Fetch per richiesta. Semplice e corretto, e il tuo CMS è ora sul percorso
critico di ogni caricamento di pagina. La sua latenza è il tuo TTFB e il suo downtime è il tuo
downtime. Va bene per una dashboard di amministrazione, sbagliato per un sito di marketing.
ISR con una finestra temporale.revalidate: 60 e il contenuto è al massimo vecchio di un minuto.
Funziona, e significa che gli editor guardano l'orologio dopo la pubblicazione, e inoltre ogni
scadenza della finestra è un cache miss che qualcuno paga.
Pre-compila, servi dalla cache. Il contenuto viene renderizzato al momento della pubblicazione e servito
come artefatto statico. Il più veloce e il più economico — finché qualcosa gestisce
l'invalidazione quando il contenuto cambia.
La maggior parte dei team parte dal primo, passa al secondo quando la fattura o la latenza fanno male, e
raggiunge il terzo collegando la revalidation on-demand a un webhook.
#Il problema dell'invalidazione, e come non averlo
La terza opzione è quella giusta, e la sua parte difficile è l'invalidazione della cache: la pagina è una
copia di un calcolo, e il calcolo potrebbe cambiare in qualsiasi momento.
corpusctl elimina il problema invece di gestirlo, rendendo l'indirizzo
stesso immutabile.
La pubblicazione esegue la pipeline di build: il contenuto viene validato, renderizzato e scritto
in un file indirizzato tramite hash nell'object storage, poi il manifest viene aggiornato.
Il client risolve lo slug in uno shard del manifest localmente, poi recupera quell'
indirizzo dalla cache edge nginx.
Poiché l'indirizzo è un hash del contenuto:
Lo stesso indirizzo non può mai restituire contenuti diversi.
È sicuro metterlo in cache per trenta giorni.
La pubblicazione scrive un nuovo indirizzo; non c'è nulla da purgare.
Due richieste HTTP, entrambe dalla cache. Il read client non porta alcun token, perché
non c'è nulla da autorizzare: il contenuto è già pubblico e già compilato.
Il manifest è suddiviso in shard, quindi uno spazio con diecimila voci scarica comunque
un piccolo file anziché un indice in crescita.
#Anteprima delle bozze: la parte che tutti collegano per ultima e di cui si pentono
Gli editor si aspettano di vedere il lavoro non pubblicato. In Next.js significa una route che
valida un segreto, abilita la modalità bozza e reindirizza.
È anche un buco di sicurezza nella maggior parte delle implementazioni fatte a mano. Due errori,
entrambi comuni:
Confrontare il segreto con ===. Il confronto tra stringhe si interrompe al
primo carattere diverso, il che fa trapelare la sua lunghezza e posizione attraverso i tempi.
Usa un confronto a tempo costante.
Reindirizzare a qualunque cosa dica slug.?slug=https://evil.example.com trasforma
il tuo endpoint di anteprima in un open redirect sul tuo stesso dominio — utile per
il phishing, e sarà trovato da uno scanner.
@corpusctl/next gestisce entrambi:
Il confronto del segreto è a tempo costante, gli URL assoluti e i percorsi relativi al protocollo
e i trucchi con backslash vengono rifiutati, e il target del reindirizzamento è il valore
che il CMS ha confermato — non quello che la richiesta ha fornito. decision.reason è un
valore stabile leggibile dalla macchina che puoi mappare sul tuo testo in qualsiasi lingua.
#Lo strato di rendering, che è dove se ne vanno le settimane
Recuperare il contenuto è un pomeriggio. Trasformarlo in markup stilizzato è il progetto,
ed è dove si arena la maggior parte delle adozioni di CMS headless.
Se la libreria client fornisce markup preconfezionato, spendi quel tempo a sovrascriverlo.
Se non fornisce nulla, spendi quel tempo a costruirlo — ma almeno stai
costruendo anziché combattere.
corpusctl adotta la seconda posizione deliberatamente. I renderer dei blocchi arrivano con
zero stile predefinito — nemmeno una riga di CSS. Ogni tipo di blocco è
sovrascrivibile. Un tipo di blocco sconosciuto viene saltato con grazia invece di generare un errore,
quindi un modello di contenuto che va oltre il front end degrada invece di
rompere una pagina.
L'albero di rendering del core è indipendente dal framework; gli adattatori React, Vue e Next.js
sono sottili strati al di sopra. La regola che c'è dietro: se renderizzare un tipo di blocco
richiede codice specifico del framework, l'astrazione è nel posto sbagliato.
Anche con contenuto pre-compilato di solito vuoi che il front end sappia che qualcosa
è cambiato — per aggiornare un elenco, riscaldare una route o invalidare una cache a valle.
corpusctl attiva i webhook su publish, unpublish, update e delete. Le consegne
stanno in una coda durevole con backoff esponenziale e jitter, quindi un'ora di
inattività del ricevitore non fa perdere eventi. I payload sono firmati con HMAC e un
timestamp, e l'URL dell'endpoint viene controllato contro l'SSRF prima ancora di essere
chiamato — gli indirizzi di rete interni vengono rifiutati alla registrazione.
Payload — un unico prodotto Next.js, config-as-code, a tuo agio con il self-hosting.
Nota che Cloud non accetta nuovi progetti a seguito dell'acquisizione da parte di Figma.
Strapi — la community più grande con ampio margine (~2.800 domande su Stack
Overflow), self-hosted gratuito. Strapi Cloud fattura per progetto.
Sanity — la migliore esperienza di editing della categoria, GROQ e prezzo
per postazione.
corpusctl — letture immutabili pre-compilate senza contatore, più progetti da
un pannello, renderer senza stile. Community più piccola; nessun marketplace; la cache
edge è a regione singola.
Contenuto renderizzato solo sul client. Hai scelto Next.js per il rendering
lato server e poi hai fatto il fetch in useEffect. I motori di ricerca vedono un guscio.
Anteprima collegata dopo il cutover. Gli editor scoprono il primo giorno che non
possono vedere le proprie bozze. Collegala per prima.
Nessuna decisione di caching presa. Ogni visualizzazione di pagina colpisce il CMS, e la fattura o
la latenza spuntano al secondo mese.
Cosa costa davvero l'"open source" in un CMS headless
Open source raramente significa gratuito da eseguire. Licenze, upsell cloud e il costo verificato di sei CMS headless popolari — con i numeri dalle loro stesse pagine.