Post del blog tradotti vuoti con deployment basato su manifest
Il Problema
Dopo il deployment su Cloudflare, gli articoli del blog tradotti (spagnolo, tedesco, francese, ecc.) venivano caricati casualmente senza contenuto. A volte funzionavano bene, altre volte no. La pagina veniva renderizzata, ma il contenuto era assente.
Cos'è un File Manifest?
I miei articoli del blog sono archiviati come file JSON nel codebase, non in un database. Questo mi permette di scrivere contenuti nel mio editor e tracciare tutto in Git. Semplice.
Un file manifest è un file JSON pre-generato che contiene tutti i dati degli articoli del blog. Le Cloudflare Workers non hanno accesso a un filesystem tradizionale al momento dell'esecuzione, possono usare solo i file inclusi durante la build. Quindi, invece di leggere i singoli file degli articoli al runtime, il processo di build crea un unico manifest con tutti gli articoli.
Il manifest viene generato al momento della build e incluso nel deployment. Al runtime, il codice legge da questo manifest invece che dal filesystem.
La Causa
La struttura del mio manifest è la seguente:
{
"slug": "my-post",
"translatedSlugs": {
"en": "my-post",
"es": "mi-publicacion"
},
"localized": {
"es": { "title": "...", "content": "..." },
"de": { "title": "...", "content": "..." }
}
}
Nota: l'inglese NON è nell'oggetto localized
. Il contenuto in inglese risiede a livello base.
La mia funzione getPostByTranslatedSlug
faceva questo:
// Ottieni il post con locale inglese per accedere a translatedSlugs
const post = getPostBySlug(slug, 'en');
// Controlla se translatedSlugs corrisponde...
if (post.translatedSlugs[someLocale] === translatedSlug) {
return getPostBySlug(slug, requestedLocale);
}
Quando chiamavo getPostBySlug(slug, 'en')
, tentava di accedere a manifest.localized.en
che non esiste, restituendo quindi contenuto vuoto.
La Soluzione
Invece di chiamare getPostBySlug(slug, 'en')
, ho modificato la funzione per usare getAllPosts()
che restituisce tutti i post con i metadati di base, inclusi translatedSlugs
:
export function getPostByTranslatedSlug(translatedSlug: string, locale: string): BlogPost | null {
// Ottieni tutti i post per accedere ai metadati di base
const allPosts = getAllPosts();
for (const post of allPosts) {
if (post.translatedSlugs) {
for (const [lang, slugValue] of Object.entries(post.translatedSlugs)) {
if (slugValue === translatedSlug) {
// Trovato! Ora ottieni la versione localizzata
return getPostBySlug(post.slug, locale);
}
}
}
}
return null;
}
Usare un File Manifest è una Buona Pratica?
Dipende dal tuo target di deployment:
Per Cloudflare Workers / Piattaforme Edge: Sì, è necessario. Queste piattaforme non hanno accesso a un filesystem tradizionale, quindi devi includere tutti i dati al momento della build.
Per server Node.js tradizionali (Vercel, AWS, ecc.): Non è richiesto. Puoi leggere dal filesystem al runtime, il che è più semplice e non richiede un passaggio di build per generare il manifest.
Il compromesso: i file manifest aggiungono complessità al tuo processo di build e possono causare bug come questo se non strutturati attentamente. Ma abilitano il deployment su piattaforme edge che sono più veloci ed economiche.
Lezione Appresa
Quando si utilizza un manifest per esportazioni statiche:
- Non dare per scontato che la locale di base esista in
localized
- I metadati di base (come
translatedSlugs
) risiedono nella root - Solo le locali non di base sono in
localized