
Next.js è uno dei framework più potenti e flessibili per lo sviluppo di applicazioni React moderne. Con l’uscita della versione 13+ e l’introduzione dell’App Router, molte pratiche consolidate come getStaticProps
e getStaticPaths
sono diventate obsolete, sostituite da un sistema più moderno, performante e scalabile. Comprendere appieno il funzionamento del fetch in Next.js 13+ è essenziale per ogni sviluppatore che voglia costruire siti performanti, scalabili e ottimizzati per SEO. In questo articolo esploreremo in dettaglio come funziona il fetch in Next.js 13+, le differenze rispetto al passato, come gestire ISR, SEO e strategie di generazione delle pagine, e daremo consigli pratici per ogni contesto, incluso il caso di un sito headless con Drupal.
Parleremo anche delle implicazioni pratiche sul workflow quotidiano, di come le nuove funzionalità riducano i tempi di build e semplifichino la gestione dei contenuti dinamici, e di come ottimizzare l’esperienza utente senza sacrificare la SEO.
Il passato: fetch con Pages Router
Prima di Next.js 13 e dell’App Router, il sistema di fetch e generazione delle pagine si basava principalmente su due funzioni principali:
-
getStaticProps
: per generare pagine statiche alla build time (Static Site Generation, SSG). -
getStaticPaths
: per indicare a Next.js quali pagine dinamiche generare già alla build.
Questo approccio funzionava bene per siti di dimensioni medio-piccole, ma mostrava rapidamente i suoi limiti su progetti grandi o con contenuti frequentemente aggiornati. Immagina un blog con centinaia o migliaia di articoli: ogni volta che un contenuto veniva modificato, era necessario attendere un rebuild completo per riflettere le modifiche online, con conseguenze evidenti su tempo di deploy e UX.
Esempio classico:
// pages/blog/[slug].js
export async function getStaticPaths() {
const res = await fetch('https://tuo-drupal.it/jsonapi/node/articolo')
const data = await res.json()
const paths = data.data.map(a => ({
params: { slug: a.attributes.path.alias.replace('/blog/', '') }
}))
return { paths, fallback: 'blocking' }
}
export async function getStaticProps({ params }) {
const res = await fetch(`https://tuo-drupal.it/jsonapi/node/articolo?filter[slug]=${params.slug}`)
const data = await res.json()
return {
props: { articolo: data.data[0] },
revalidate: 60
}
}
Qui:
-
SSG generava le pagine alla build, rendendo la navigazione super veloce per l’utente.
-
ISR (
revalidate
) permetteva di rigenerare le pagine in background a intervalli regolari. -
fallback: 'blocking'
garantiva che i crawler ricevessero HTML completo, fondamentale per SEO.
Il problema principale era la scalabilità: build lunghe, deploy complessi e gestione dei contenuti poco flessibile.
Il presente: App Router (Next.js 13+)
Con l’introduzione dell’App Router, Next.js ha rivoluzionato il concetto di routing e fetch dei dati, portando un paradigma più flessibile e modulare. Ora il fetch può avvenire direttamente nei Server Components, che vengono renderizzati lato server alla richiesta, senza separare logica di dati e render. Questo semplifica enormemente la manutenzione e aumenta le performance, riducendo il tempo di build e ottimizzando l’esperienza utente.
Le novità principali:
-
Server Components: componenti React renderizzati sul server con accesso nativo ai dati.
-
generateStaticParams()
: sostituiscegetStaticPaths
per definire quali pagine generare alla build. -
revalidate
: mantiene ISR, definendo la frequenza di rigenerazione delle pagine. -
On-demand generation: le pagine non pre-generate vengono create alla prima richiesta, con caching incluso.
La grande differenza rispetto al passato è che non serve più separare logica fetch e rendering, rendendo il codice più pulito e facilmente leggibile.
Struttura tipica App Router per un blog
src/
app/
blog/
page.js ← lista articoli
[slug]/
page.js ← dettaglio articolo
-
page.js
nella cartella[slug]
gestisce il dettaglio degli articoli. -
generateStaticParams()
indica quali articoli generare alla build. -
Tutte le altre pagine vengono create al volo tramite ISR con fallback, permettendo scalabilità anche con migliaia di contenuti.
Esempio di Server Component con fetch e ISR
// src/app/blog/[slug]/page.js
export async function generateStaticParams() {
const res = await fetch('https://tuo-drupal.it/jsonapi/node/articolo')
const data = await res.json()
return data.data.slice(0, 10).map(a => ({
slug: a.attributes.path.alias.replace('/blog/', '')
}))
}
export const revalidate = 60 // ISR: rigenera ogni 60 secondi
export default async function ArticoloPage({ params }) {
const res = await fetch(`https://tuo-drupal.it/jsonapi/node/articolo?filter[slug]=${params.slug}`, {
next: { revalidate }
})
const data = await res.json()
const articolo = data.data[0]
return (
<article>
<h1>{articolo.attributes.title}</h1>
<div dangerouslySetInnerHTML={{ __html: articolo.attributes.body.value }} />
</article>
)
}
Cosa succede qui:
Nel nostro esempio, la funzione generateStaticParams()
viene utilizzata per indicare a Next.js quali pagine generare già alla build. Qui prendiamo solo i primi dieci articoli, quindi Next.js pre-renderizza solo queste dieci pagine in HTML statico. Questo garantisce che le pagine principali siano immediatamente disponibili agli utenti e ai crawler SEO, con tempi di caricamento rapidissimi e contenuti già pronti per l’indicizzazione. Il numero dieci non è fisso: è stato scelto a scopo illustrativo, ma in un progetto reale potresti pre-generare tutte le pagine principali, oppure solo quelle più recenti o più importanti.
Per tutte le altre pagine che non sono state generate alla build, Next.js le crea on-demand alla prima richiesta. Quando un utente visita uno di questi articoli, il Server Component viene eseguito, fetchando i dati dal CMS e generando il markup HTML lato server. La pagina viene servita immediatamente all’utente e salvata per le richieste successive, evitando di generare 404. Questo comportamento permette di scalare il sito senza dover pre-generare ogni singolo contenuto.
Inoltre, la rigenerazione periodica delle pagine è gestita tramite la costante revalidate
. Nel nostro esempio, ogni 60 secondi Next.js verifica se una pagina richiesta deve essere aggiornata in background. La nuova versione diventa disponibile per le richieste successive, senza che l’utente debba aspettare, garantendo contenuti sempre freschi.
Infine, perché tutto ciò funzioni in modo ottimale anche per la SEO, l’HTML viene generato lato server grazie ai Server Components. I crawler ricevono subito il contenuto completo, senza dover eseguire JavaScript, e gli utenti sperimentano tempi di caricamento rapidissimi, con pagine già renderizzate e pronte per essere visualizzate. In questo modo, Next.js combina scalabilità, aggiornamento continuo dei contenuti e SEO perfetta senza compromessi.
Spiegazione di ISR (Incremental Static Regeneration)
Prima dell’introduzione dell’ISR, Next.js offriva due principali strategie per generare pagine: Static Site Generation (SSG) e Server Side Rendering (SSR). Con SSG, tutte le pagine venivano generate alla build, il che garantiva performance eccellenti per l’utente finale, ma diventava rapidamente poco scalabile quando i contenuti crescevano. Ogni modifica richiedeva un rebuild completo del sito, aumentando i tempi di deploy e rendendo complesso aggiornare contenuti frequentemente.
D’altra parte, SSR generava le pagine a runtime per ogni richiesta. Questo approccio permetteva di avere contenuti sempre aggiornati, ma introduceva un carico maggiore sul server e aumentava i tempi di risposta per l’utente, soprattutto con siti grandi o traffico intenso.
È qui che entra in gioco ISR (Incremental Static Regeneration), che combina i vantaggi di SSG e SSR: alcune pagine vengono generate alla build, altre vengono create on-demand alla prima richiesta, e tutte possono essere rigenerate periodicamente in background. In pratica, ISR è il compromesso ideale tra performance, scalabilità e aggiornamento dei contenuti.
Con ISR succede che:
-
Le prime pagine più importanti o generiche vengono generate già alla build, garantendo performance ottimali e SEO immediata.
-
Le pagine meno rilevanti o meno visitate vengono generate solo quando vengono richieste per la prima volta, evitando di sovraccaricare la build.
-
Le pagine già generate possono essere rigenerate periodicamente tramite il parametro
revalidate
, aggiornando i contenuti senza dover rifare il rebuild completo del sito.
Questo approccio è particolarmente utile per:
-
Blog grandi o siti con migliaia di articoli.
-
CMS headless come Drupal, dove i contenuti cambiano frequentemente.
-
SEO: i crawler ricevono sempre HTML completo, pronto per l’indicizzazione.
-
Performance: le prime richieste possono essere leggermente più lente per le pagine generate on-demand, ma tutte le successive sono servite come statiche e velocissime.
In sintesi, ISR permette di avere contenuti sempre aggiornati, pagine performanti e una gestione scalabile senza sacrificare né la SEO né l’esperienza utente.
Strategie per scegliere quali pagine generare subito
Per ottimizzare build e performance:
-
Homepage e categorie principali → generare sempre alla build.
-
Articoli più recenti o top → generare alla build per SEO e UX.
-
Articoli meno rilevanti → fallback ISR, generati on-demand.
Così:
-
Build rapida anche con migliaia di articoli.
-
SEO immediata sulle pagine principali.
-
Aggiornamento continuo dei contenuti senza rebuild manuale.
Fetch in Next.js 13+: best practice
-
Usare fetch nativo nei Server Components: integrato, pulito, supporta ISR via
{ next: { revalidate: X } }
. -
Evitare client-side fetch per contenuti critici SEO: garantisce HTML completo per i crawler.
-
Pre-generare solo le pagine principali: riduce build time e costi di deploy.
-
Usare fallback ‘blocking’ per SEO: garantisce HTML completo.
-
Collegamento con CMS headless: Drupal JSON:API o GraphQL sono perfetti provider.
Differenze chiave Pages Router vs App Router
Concetto | Pages Router | App Router 13+ |
---|---|---|
Generazione pagine statiche | getStaticProps / getStaticPaths | generateStaticParams + Server Components |
ISR | revalidate in getStaticProps | revalidate a livello di fetch nei Server Components |
Fetch dati | Separato dal render | Diretto nei Server Components |
Scalabilità | Lenta per migliaia di pagine | Massima: pre-generate solo pagine principali, resto on-demand |
SEO | fallback: blocking necessario | fallback “blocking” automatico via Server Components |
Build time | Lungo con molti articoli | Rapido, build solo per pagine principali |
Conclusioni
Con l’App Router di Next.js 13+, il fetch dei dati diventa più semplice, scalabile e performante.
Se prima getStaticProps
e getStaticPaths
erano lo standard, ora:
-
Server Components + fetch nativo → codice più pulito e diretto.
-
ISR con revalidate + generateStaticParams → perfetto compromesso tra performance, SEO e scalabilità.
-
Fallback on-demand → genera solo le pagine necessarie, riduce build time e aumenta la velocità del deploy.
Per siti headless come Drupal, questa strategia è ideale: contenuti aggiornati, SEO perfetto, esperienza utente ottimale e deploy super leggero.
In sintesi: se vuoi performance, SEO e scalabilità, il futuro del fetch in Next.js 13+ è App Router + Server Components + ISR. Addio vecchie funzioni e build lente, benvenuto nel mondo moderno del frontend headless.