Come abbiamo ridotto le risposte lente dell'80%

Subito è uno dei principali marketplace in Italia. Gestiamo migliaia di richieste ogni minuto. La nostra pagina di dettaglio dell'annuncio è fondamentale per la SEO e per i ricavi.

Abbiamo spostato questa pagina dal Pages Router di Next.js all'App Router. Non abbiamo interrotto lo sviluppo del prodotto per farlo; abbiamo proceduto per piccoli passi.

Ecco come abbiamo fatto.

L'Approccio

Abbiamo utilizzato una strategia incrementale. Abbiamo aggiunto l'albero dell'App Router accanto al vecchio Pages Router. Questo ci ha permesso di rilasciare nuove funzionalità durante la migrazione.

Abbiamo utilizzato i Server Components per gestire il data fetching. Ciò ha eliminato la necessità di passare i dati attraverso molti livelli. Abbiamo anche creato un Data Access Layer, garantendo che i dati venissero recuperati una sola volta per richiesta.

Abbiamo utilizzato Suspense e l'hook use() per abilitare l'HTML streaming. Questo mostra uno skeleton screen mentre i dati vengono caricati, permettendo all'utente di visualizzare la pagina più velocemente.

Le Sfide

Problema 1: HTTP 410 Gone I motori di ricerca necessitano di uno stato 410 quando una pagina viene rimossa permanentemente. L'App Router non ha un modo integrato per inviarlo. Abbiamo risolto il problema utilizzando il nostro server Express: il server intercetta la risposta e cambia il codice di stato.

Problema 2: HTML Streaming Abbiamo riscontrato che i nostri skeleton di caricamento non apparivano. La pagina rimaneva bianca per diversi secondi.

Abbiamo scoperto che Nginx e Akamai stavano effettuando il buffering delle nostre risposte. Se il CDN effettua il buffering dell'HTML, lo streaming fallisce. Abbiamo dovuto disattivare il buffering in Nginx e applicare impostazioni personalizzate in Akamai. Una volta risolto il problema, il contenuto è stato trasmesso perfettamente all'utente.

Il Rollout

Abbiamo effettuato il rollout in due fasi per proteggere la nostra SEO.

Fase 1: Abbiamo spostato il traffico sull'App Router ma abbiamo mantenuto lo streaming disattivato. Abbiamo proceduto una categoria alla volta.

Fase 2: Abbiamo abilitato l'HTML streaming. Abbiamo testato questa funzione prima su categorie piccole. Il nostro team SEO ha monitorato i posizionamenti per due settimane prima di passare alla categoria successiva.

I Risultati

I risultati sono stati enormi. Prima della migrazione, fino al 40% delle nostre risposte era lento. Dopo la migrazione, le risposte lente sono diminuite dell'80%.

La maggior parte delle pagine ora si carica in meno di 500ms.

Lezioni apprese

Come abbiamo ridotto le risposte lente dell'80% migrando a Next.js App Router

Nel nostro costante impegno per migliorare le prestazioni della nostra piattaforma, ci siamo trovati ad affrontare una sfida critica: tempi di risposta eccessivamente lenti. Inizialmente, pensavamo che il problema risiedesse nel database o nella latenza di rete, ma la realtà era più complessa e legata all'architettura della nostra applicazione.

Il problema: I limiti del Pages Router

Utilizzando il Pages Router di Next.js, la nostra applicazione soffriva di due problemi principali che impattavano pesantemente l'esperienza utente:

  1. Bundle JavaScript eccessivi: Poiché quasi tutti i componenti venivano inviati al client per l'idratazione, il peso dei file JS era enorme. Questo causava tempi di interattività (TTI) molto elevati, specialmente sui dispositivi mobili.
  2. Waterfall di richieste dati: La struttura del Pages Router ci costringeva spesso a eseguire il fetching dei dati in modo sequenziale, creando una "cascata" di richieste che rallentava drasticamente il caricamento della pagina.

La soluzione: Migrazione all'App Router

La decisione di migrare all'App Router è stata dettata dalla necessità di sfruttare le nuove funzionalità di React e Next.js per ottimizzare il caricamento. Ecco come abbiamo trasformato le nostre prestazioni:

1. React Server Components (RSC)

Con l'App Router, abbiamo potuto implementare i React Server Components. A differenza dei componenti tradizionali, i RSC vengono eseguiti esclusivamente sul server. Questo ci ha permesso di:

2. Data Fetching ottimizzato

L'App Router introduce un modello di fetching dei dati molto più efficiente. Invece di dover caricare tutto tramite getServerSideProps, ora possiamo eseguire il fetching direttamente all'interno dei componenti. Grazie al caching integrato di Next.js, le richieste ripetute vengono ottimizzate automaticamente, riducendo il carico sul server e i tempi di attesa.

3. Streaming e Suspense

Uno dei cambiamenti più impattanti è stato l'uso dello streaming. Utilizzando i componenti <Suspense> di React, abbiamo potuto inviare parti della pagina al client non appena sono pronte, invece di aspettare che l'intera pagina fosse generata sul server.

Questo significa che l'utente vede immediatamente la struttura della pagina e i contenuti statici, mentre i componenti più lenti (come i widget di dati in tempo reale) vengono caricati in modo asincrono non appena i dati sono disponibili.

Risultati ottenuti

Dopo la migrazione, i nostri KPI hanno mostrato un miglioramento straordinario:

Metrica Miglioramento
TTFB (Time to First Byte) -50%
Dimensione Bundle JS -60%
Tempi di risposta complessivi -80%

Conclusione

La migrazione all'App Router non è stata priva di sfide, specialmente per quanto riguarda la gestione dello stato tra componenti server e client, ma i benefici in termini di prestazioni e scalabilità sono stati innegabili. Se la vostra applicazione sta soffrendo a causa di bundle pesanti o tempi di caricamento elevati, il passaggio all'App Router potrebbe essere la chiave per sbloccare le prestazioni del vostro prodotto.