Una guida completa alla rigenerazione statica incrementale (ISR) con Next.js
Pubblicato: 2022-03-10Un anno fa, Next.js 9.3 ha rilasciato il supporto per Static Site Generation (SSG), rendendolo il primo framework ibrido. Sono stato un utente felice di Next.js per circa alcuni anni a questo punto, ma questa versione ha reso Next.js la mia nuova soluzione predefinita. Dopo aver lavorato a lungo con Next.js, mi sono unito a Vercel per aiutare aziende come Tripadvisor e Washington Post nell'adozione e nella scalabilità di Next.js.
In questo articolo, vorrei esplorare una nuova evoluzione di Jamstack: Incremental Static Regeneration (ISR) . Di seguito troverai una guida all'ISR, inclusi casi d'uso, demo e compromessi.
Il problema con la generazione di siti statici
L'idea alla base di Jamstack è interessante: pagine statiche pre-renderizzate che possono essere inviate a un CDN e disponibili a livello globale in pochi secondi. Il contenuto statico è veloce, resistente ai tempi di inattività e immediatamente indicizzato dai crawler. Ma ci sono alcuni problemi.
Se hai adottato l'architettura Jamstack durante la creazione di un sito statico su larga scala, potresti dover aspettare ore per la creazione del tuo sito. Se raddoppi il numero di pagine, raddoppia anche il tempo di costruzione. Consideriamo Target.com. È possibile generare staticamente milioni di prodotti con ogni distribuzione?
Anche se ogni pagina fosse generata staticamente in un irrealistico 1ms, ci vorrebbero comunque ore per ricostruire l'intero sito . Per le applicazioni Web di grandi dimensioni, la scelta della generazione completa di siti statici non è un'operazione di partenza. I team su larga scala hanno bisogno di una soluzione ibrida più flessibile, personalizzata.
Sistemi di gestione dei contenuti (CMS)
Per molti team, il contenuto del loro sito è disaccoppiato dal codice. L'utilizzo di un CMS Headless consente agli editor di contenuti di pubblicare le modifiche senza coinvolgere uno sviluppatore. Tuttavia, con i siti statici tradizionali, questo processo può essere lento.
Prendi in considerazione un negozio di e-commerce con 100.000 prodotti. I prezzi dei prodotti cambiano frequentemente. Quando un editor di contenuti modifica il prezzo delle cuffie da $ 100 a $ 75 come parte di una promozione, il suo CMS utilizza un webhook per ricostruire l'intero sito. Non è possibile attendere ore prima che il nuovo prezzo si rifletta.
Anche le build lunghe con calcoli non necessari potrebbero comportare spese aggiuntive. Idealmente, la tua applicazione è abbastanza intelligente da capire quali prodotti sono cambiati e aggiornare in modo incrementale quelle pagine senza che sia necessaria una ricostruzione completa .
Rigenerazione statica incrementale (ISR)
Next.js ti consente di creare o aggiornare pagine statiche dopo aver creato il tuo sito. La rigenerazione statica incrementale (ISR) consente agli sviluppatori e agli editor di contenuti di utilizzare la generazione statica per pagina, senza dover ricostruire l'intero sito . Con ISR, puoi conservare i vantaggi dell'elettricità statica scalando fino a milioni di pagine.
Le pagine statiche possono essere generate in fase di esecuzione (su richiesta) anziché in fase di compilazione con ISR. Utilizzando analisi, test A/B o altre metriche, sei dotato della flessibilità per fare il tuo compromesso sui tempi di costruzione.
Considera l'e-commerce di prima con 100.000 prodotti. A 50 ms realistici per generare staticamente ogni pagina di prodotto, questo richiederebbe quasi 2 ore senza ISR . Con ISR possiamo scegliere tra:
- Costruzioni più veloci
Genera i 1.000 prodotti più popolari in fase di compilazione. Le richieste fatte ad altri prodotti mancheranno la cache e genereranno staticamente build on-demand: 1 minuto. - Tasso di successo della cache più elevato
Genera 10.000 prodotti in fase di compilazione, assicurandoti che più prodotti vengano memorizzati nella cache prima della richiesta dell'utente: build da 8 minuti.
Esaminiamo un esempio di ISR per una pagina di prodotto di e-commerce.
Iniziare
Recuperando i dati
Se non hai mai usato Next.js prima, ti consiglio di leggere Guida introduttiva a Next.js per comprendere le basi. ISR utilizza la stessa API Next.js per generare pagine statiche: getStaticProps
. Specificando revalidate: 60
, informiamo Next.js di utilizzare ISR per questa pagina.
- Next.js può definire un tempo di riconvalida per pagina. Impostiamolo a 60 secondi.
- La richiesta iniziale alla pagina del prodotto mostrerà la pagina memorizzata nella cache con il prezzo originale.
- I dati del prodotto vengono aggiornati nel CMS.
- Eventuali richieste alla pagina dopo la richiesta iniziale e prima di 60 secondi vengono memorizzate nella cache e istantanee.
- Dopo la finestra di 60 secondi, la richiesta successiva mostrerà ancora la pagina memorizzata nella cache (non aggiornata). Next.js attiva una rigenerazione della pagina in background .
- Una volta che la pagina è stata generata correttamente, Next.js invaliderà la cache e mostrerà la pagina del prodotto aggiornata. Se la rigenerazione in background non riesce, la vecchia pagina rimane inalterata.
// pages/products/[id].js export async function getStaticProps({ params }) { return { props: { product: await getProductFromDatabase(params.id) }, revalidate: 60 } }
Generazione di percorsi
Next.js definisce quali prodotti generare in fase di compilazione e quali su richiesta. Generiamo solo i 1.000 prodotti più popolari in fase di compilazione fornendo a getStaticPaths
un elenco dei primi 1.000 ID prodotto.
È necessario configurare il modo in cui Next.js eseguirà il "fallback" quando si richiede uno qualsiasi degli altri prodotti dopo la build iniziale. Ci sono due opzioni tra cui scegliere: blocking
e true
.
-
fallback: blocking
(preferito)
Quando viene effettuata una richiesta a una pagina che non è stata generata, Next.js eseguirà il rendering della pagina sul server alla prima richiesta. Le richieste future serviranno il file statico dalla cache. -
fallback: true
Quando viene effettuata una richiesta a una pagina che non è stata generata, Next.js servirà immediatamente una pagina statica con uno stato di caricamento alla prima richiesta. Al termine del caricamento dei dati, la pagina verrà nuovamente visualizzata con i nuovi dati e verrà memorizzata nella cache. Le richieste future serviranno il file statico dalla cache.
// pages/products/[id].js export async function getStaticPaths() { const products = await getTop1000Products() const paths = products.map((product) => ({ params: { id: product.id } })) return { paths, fallback: 'blocking' } }
Compromessi
Next.js si concentra prima di tutto sull'utente finale. La "soluzione migliore" è relativa e varia in base al settore, al pubblico e alla natura dell'applicazione. Consentendo agli sviluppatori di passare da una soluzione all'altra senza uscire dai limiti del framework, Next.js ti consente di scegliere lo strumento giusto per il progetto.
Rendering lato server
L'ISR non è sempre la soluzione giusta. Ad esempio, il feed delle notizie di Facebook non può mostrare contenuti obsoleti. In questo caso, vorresti utilizzare SSR e potenzialmente le tue intestazioni cache-control
con chiavi surrogate per invalidare il contenuto. Poiché Next.js è un framework ibrido, puoi fare quel compromesso da solo e rimanere all'interno del framework.
// You can cache SSR pages at the edge using Next.js // inside both getServerSideProps and API Routes res.setHeader('Cache-Control', 's-maxage=60, stale-while-revalidate');
SSR e edge caching sono simili a ISR (soprattutto se si utilizzano intestazioni di caching stale-while-revalidate
) con la differenza principale che è la prima richiesta. Con ISR, la prima richiesta può essere garantita statica se pre-renderizzata. Anche se il database non funziona o si verifica un problema di comunicazione con un'API, i tuoi utenti vedranno comunque la pagina statica correttamente servita. Tuttavia, SSR ti consentirà di personalizzare la tua pagina in base alla richiesta in arrivo.
Nota : l'utilizzo di SSR senza memorizzazione nella cache può comportare prestazioni scadenti. Ogni millisecondo è importante quando si impedisce all'utente di vedere il tuo sito e questo può avere un effetto drammatico sul tuo TTFB (Time to First Byte).
Generazione di siti statici
L'ISR non ha sempre senso per i piccoli siti web. Se il tuo periodo di riconvalida è maggiore del tempo necessario per ricostruire l'intero sito, potresti anche utilizzare la tradizionale generazione di siti statici.
Rendering lato client
Se usi React senza Next.js, stai usando il rendering lato client. La tua applicazione serve uno stato di caricamento, seguito dalla richiesta di dati all'interno di JavaScript sul lato client (ad esempio useEffect
). Sebbene ciò aumenti le tue opzioni per l'hosting (poiché non è necessario un server), ci sono dei compromessi.
La mancanza di contenuto pre-renderizzato dall'HTML iniziale porta a un'ottimizzazione dei motori di ricerca (SEO) più lenta e meno dinamica. Inoltre, non è possibile utilizzare CSR con JavaScript disabilitato.
Opzioni di riserva ISR
Se i tuoi dati possono essere recuperati rapidamente, prendi in considerazione l'utilizzo di fallback: blocking
. Quindi, non è necessario considerare lo stato di caricamento e la tua pagina mostrerà sempre lo stesso risultato (indipendentemente dal fatto che sia memorizzata nella cache o meno). Se il recupero dei dati è lento, fallback: true
ti consente di mostrare immediatamente uno stato di caricamento all'utente.
ISR: Non solo memorizzazione nella cache!
Anche se ho spiegato ISR attraverso il contesto di una cache, è progettato per rendere persistenti le pagine generate tra le distribuzioni. Ciò significa che puoi tornare indietro all'istante e non perdere le pagine generate in precedenza.
Ogni distribuzione può essere codificata da un ID, che Next.js utilizza per rendere persistenti le pagine generate staticamente. Quando esegui il rollback, puoi aggiornare la chiave in modo che punti alla distribuzione precedente, consentendo distribuzioni atomiche. Ciò significa che puoi visitare le tue precedenti distribuzioni immutabili e funzioneranno come previsto.
- Ecco un esempio di ripristino del codice con ISR:
- Invii il codice e ottieni un ID distribuzione 123.
- La tua pagina contiene un errore di battitura "Smshng Magazine".
- Aggiorna la pagina nel CMS. Non è necessario ridistribuire.
- Una volta che la tua pagina mostra "Smashing Magazine", viene conservata nella memoria.
- Invii un codice errato e distribuisci l'ID 345.
- Si esegue il rollback all'ID distribuzione 123.
- Vedi ancora "Smashing Magazine".
Il ripristino e la persistenza delle pagine statiche non rientrano nell'ambito di Next.js e dipendono dal provider di hosting. Si noti che ISR differisce dal rendering del server con le intestazioni Cache-Control
perché, in base alla progettazione, le cache scadono. Non sono condivisi tra le regioni e verranno eliminati al ripristino.
Esempi di rigenerazione statica incrementale
La rigenerazione statica incrementale funziona bene per e-commerce, pagine di marketing, post di blog, media supportati da pubblicità e altro ancora.
- Demo e-commerce
Next.js Commerce è uno starter kit all-in-one per siti di e-commerce ad alte prestazioni. - Demo sulle reazioni di GitHub
Reagisci al problema originale di GitHub e osserva ISR aggiornare la pagina di destinazione generata staticamente. - Demo di Tweet statici
Questo progetto viene distribuito in 30 secondi, ma può generare staticamente 500 milioni di tweet su richiesta utilizzando ISR.
Scopri Next.js oggi
Gli sviluppatori e i grandi team scelgono Next.js per il suo approccio ibrido e la capacità di generare pagine on-demand in modo incrementale. Con ISR, ottieni i vantaggi dello statico con la flessibilità del rendering del server. ISR funziona immediatamente utilizzando il next start
.
Next.js è stato progettato per un'adozione graduale. Con Next.js, puoi continuare a utilizzare il tuo codice esistente e aggiungere quanto (o poco) React di cui hai bisogno. Iniziando in piccolo e aggiungendo in modo incrementale più pagine, puoi prevenire il deragliamento del lavoro sulle funzionalità evitando una riscrittura completa. Scopri di più su Next.js e buona programmazione a tutti!
Ulteriori letture
- Introduzione a Next.js
- Confronto dei metodi di stile in Next.js
- Come creare un server GraphQL utilizzando i percorsi API Next.js