Come velocizzare la tua app Next.js con strategie di suddivisione del codice e caricamento intelligente.
Data di pubblicazione: 8 novembre 2019
Scopri i diversi tipi di suddivisione del codice e come utilizzare le importazioni dinamiche per velocizzare le tue app Next.js.
Suddivisione del codice basata su route e componenti
Per impostazione predefinita, Next.js suddivide il codice JavaScript in blocchi separati per ogni route. Quando gli utenti caricano l'applicazione, Next.js invia solo il codice necessario per la route iniziale. Quando gli utenti navigano nell'applicazione, recuperano i chunk associati alle altre route. La suddivisione del codice basata sulle route riduce al minimo la quantità di script che deve essere analizzata e compilata contemporaneamente, il che si traduce in tempi di caricamento della pagina più rapidi.
Sebbene la suddivisione del codice basata sulle route sia una buona impostazione predefinita, puoi ottimizzare ulteriormente il processo di caricamento con la suddivisione del codice a livello di componente. Se la tua app contiene componenti di grandi dimensioni, è consigliabile suddividerli in blocchi separati. In questo modo, tutti i componenti di grandi dimensioni che non sono critici o vengono visualizzati solo in determinate interazioni dell'utente (ad esempio, quando fa clic su un pulsante) possono essere caricati in modalità differita.
Next.js supporta l'importazione dinamicaimport(), che ti consente di importare dinamicamente moduli JavaScript (inclusi i componenti React) e caricare ogni importazione come un chunk separato. In questo modo, puoi
dividere il codice a livello di componente e controllare il caricamento delle risorse in modo
che gli utenti scarichino solo il codice necessario per la parte del sito che
stanno visualizzando. In Next.js, questi componenti vengono renderizzati lato server
(SSR)
per impostazione predefinita.
Importazioni dinamiche in azione
Questo post include diverse versioni di un'app di esempio costituita da una semplice pagina con un pulsante. Quando fai clic sul pulsante, vedi un cucciolo carino. Man mano che avanzi nelle varie versioni dell'app, vedrai in che modo le importazioni dinamiche differiscono dalle importazioni statiche e come utilizzarle.
Nella prima versione dell'app, il cucciolo vive a components/Puppy.js. Per
visualizzare il cucciolo nella pagina, l'app importa il componente Puppy in
index.js con un'istruzione di importazione statica:
import Puppy from "../components/Puppy";
Per vedere come Next.js raggruppa l'app, esamina la traccia di rete in DevTools:
Per visualizzare l'anteprima del sito, premi Visualizza app, quindi premi Schermo intero
.
Premi "Control+Maiusc+J" (o "Command+Opzione+J" su Mac) per aprire DevTools.
Fai clic sulla scheda Rete.
Seleziona la casella di controllo Disattiva cache.
Ricarica la pagina.
Quando carichi la pagina, tutto il codice necessario, incluso il componente Puppy.js, viene raggruppato in index.js:
Quando premi il pulsante Fai clic qui, alla scheda Rete viene aggiunta solo la richiesta del JPEG del cucciolo:
Lo svantaggio di questo approccio è che, anche se gli utenti non fanno clic sul pulsante per
vedere il cucciolo, devono caricare il componente Puppy perché è incluso in
index.js. In questo piccolo esempio non è un problema, ma nelle applicazioni reali
spesso è un enorme miglioramento caricare i componenti di grandi dimensioni solo quando
necessario.
Ora dai un'occhiata a una seconda versione dell'app, in cui l'importazione statica viene
sostituita da un'importazione dinamica. Next.js include next/dynamic, che consente di utilizzare importazioni dinamiche per qualsiasi componente in Next:
import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";
// ...
const Puppy = dynamic(import("../components/Puppy"));
Segui i passaggi del primo esempio per esaminare la traccia di rete.
Quando carichi l'app per la prima volta, viene scaricato solo index.js. Questa volta è
0,5 KB più piccolo (è passato da 37,9 KB a 37,4 KB) perché
non include il codice per il componente Puppy:
Il componente Puppy ora si trova in un chunk separato, 1.js, che viene caricato solo
quando premi il pulsante:
Nelle applicazioni reali, i componenti sono spesso molto più grandi e il caricamento differito può ridurre il payload JavaScript iniziale di centinaia di kilobyte.
Importazioni dinamiche con indicatore di caricamento personalizzato
Quando carichi le risorse in modalità differita, è buona norma fornire un indicatore di caricamento
in caso di ritardi. In Next.js, puoi farlo fornendo un argomento aggiuntivo alla funzione dynamic():
const Puppy = dynamic(() => import("../components/Puppy"), {
loading: () => <p>Loading...</p>
});
Per vedere l'indicatore di caricamento in azione, simula una connessione di rete lenta in DevTools:
Per visualizzare l'anteprima del sito, premi Visualizza app, quindi premi Schermo intero
.
Premi "Control+Maiusc+J" (o "Command+Opzione+J" su Mac) per aprire DevTools.
Fai clic sulla scheda Rete.
Seleziona la casella di controllo Disattiva cache.
Nell'elenco a discesa Limitazione, seleziona 3G veloce.
Premi il pulsante Fai clic qui.
Ora, quando fai clic sul pulsante, il caricamento del componente richiede un po' di tempo e l'app mostra nel frattempo il messaggio "Caricamento…".
Importazioni dinamiche senza SSR
Se devi eseguire il rendering di un componente solo sul lato client (ad esempio, un widget di chat), puoi farlo impostando l'opzione ssr su false:
const Puppy = dynamic(() => import("../components/Puppy"), {
ssr: false,
});
Conclusione
Grazie al supporto delle importazioni dinamiche, Next.js offre la suddivisione del codice a livello di componente, che può ridurre al minimo i payload JavaScript e migliorare i tempi di caricamento dell'applicazione. Per impostazione predefinita, tutti i componenti vengono sottoposti a rendering lato server e puoi disattivare questa opzione ogni volta che è necessario.