Suddivisione del codice con React.lazy e Suspense

Non devi mai inviare agli utenti più codice del necessario, quindi dividi i tuoi bundle per assicurarti che questo non accada mai.

Il metodo React.lazy semplifica la suddivisione del codice di un'applicazione React su una utilizzando le importazioni dinamiche.

import React, { lazy } from 'react';

const AvatarComponent = lazy(() => import('./AvatarComponent'));

const DetailsComponent = () => (
  <div>
    <AvatarComponent />
  </div>
)

Perché è utile?

Un'applicazione React di grandi dimensioni è solitamente composta da molti componenti, e librerie di terze parti. Se non viene fatto alcuno sforzo per provare a caricare le diverse parti di un'applicazione solo quando sono necessarie, un'unica di JavaScript verrà spedito agli utenti non appena caricano il prima pagina. Ciò può influire notevolmente sulle prestazioni della pagina.

La funzione React.lazy fornisce un modo integrato per separare i componenti in un dell'applicazione in blocchi separati di JavaScript con un lavoro di pochi elementi. Puoi quindi si occupa di caricare gli stati quando lo accoppi con il componente Suspense di strumento di authoring.

Thriller

Il problema della spedizione di un grande payload JavaScript agli utenti è la lunghezza Tempo necessario al caricamento della pagina, in particolare sui dispositivi più deboli e connessioni di rete. Questo è il motivo per cui la suddivisione del codice e il caricamento lento estremamente utile.

Tuttavia, ci sarà sempre un leggero ritardo che gli utenti riscontrano quando un componente di suddivisione del codice viene recuperato sulla rete, quindi è importante mostrano uno stato di caricamento utile. Utilizzo di React.lazy con Suspense aiuta a risolvere questo problema.

import React, { lazy, Suspense } from 'react';

const AvatarComponent = lazy(() => import('./AvatarComponent'));

const renderLoader = () => <p>Loading</p>;

const DetailsComponent = () => (
  <Suspense fallback={renderLoader()}>
    <AvatarComponent />
  </Suspense>
)

Suspense accetta un componente fallback che ti consente di visualizzare qualsiasi reazione come stato di caricamento. Il seguente esempio mostra come funziona. L'avatar viene visualizzato solo quando l'utente fa clic sul pulsante, nel caso in cui venga generata una richiesta quindi fatto per recuperare il codice necessario per lo AvatarComponent sospeso. Nel frattempo, viene visualizzato il componente di caricamento di riserva.

Qui, il codice che costituisce AvatarComponent è piccolo, il motivo per cui la rotellina di caricamento viene visualizzata solo per un breve periodo di tempo. Più grande il caricamento dei componenti può richiedere molto più tempo, in particolare e connessioni di rete deboli.

Per dimostrare meglio come funziona questa procedura:

  • Per visualizzare l'anteprima del sito, premi Visualizza app. Quindi premi Schermo intero schermo intero.
  • Premi "Ctrl+Maiusc+J" (o "Comando+Opzione+J" su Mac) per aprire DevTools.
  • Fai clic sulla scheda Rete.
  • Fai clic sul menu a discesa Limitazione, che per impostazione predefinita è impostata su Nessuna limitazione. Seleziona 3G veloce.
  • Fai clic sul pulsante Click Me (Fai clic qui) nell'app.

Ora l'indicatore di caricamento sarà visibile per un periodo più lungo. Nota come tutto il codice che l'elemento AvatarComponent viene recuperato come un blocco separato.

Riquadro di rete DevTools che mostra il download di un file chunk.js

Sospensione di più componenti

Un'altra funzionalità di Suspense è che ti consente di sospendere più il caricamento dei componenti, anche se sono tutti caricati tramite caricamento lento.

Ad esempio:

import React, { lazy, Suspense } from 'react';

const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));

const renderLoader = () => <p>Loading</p>;

const DetailsComponent = () => (
  <Suspense fallback={renderLoader()}>
    <AvatarComponent />
    <InfoComponent />
    <MoreInfoComponent />
  </Suspense>
)

Si tratta di un modo estremamente utile per ritardare il rendering di più componenti che mostra un solo stato di caricamento. Una volta completati tutti i componenti il recupero, l'utente può vederli tutti visualizzati contemporaneamente.

Puoi verificarlo con il seguente incorporamento:

Senza questi dati, è facile incorrere nel problema del caricamento sfalsato parti diverse di un'interfaccia utente che vengono caricate una dopo l'altra, ognuna con la propria indicatore di caricamento. Questo può rendere l'esperienza utente più fastidiosa.

Gestire gli errori di caricamento

Suspense ti consente di mostrare uno stato di caricamento temporaneo mentre la rete vengono effettuate in background. Ma cosa succede se le richieste di rete non vanno a buon fine un motivo? Potresti essere offline oppure la tua app web sta tentando di eseguire il caricamento lento di un URL sottoposto al controllo delle versioni. non aggiornato e non più disponibile dopo un nuovo deployment del server.

La reazione ha uno schema standard per una gestione agevole di questi tipi di caricamento errori: utilizzo di un limite di errore. Come descritto nella documentazione, qualsiasi componente di reazione può fungere da confine di errore se implementa uno (o entrambi) dei metodi del ciclo di vita static getDerivedStateFromError() componentDidCatch().

Per rilevare e gestire gli errori di caricamento lento, puoi eseguire il wrapping di Suspense con un componente principale che funge da limite di errore. All'interno errore del metodo render() di limite, puoi eseguire il rendering degli elementi secondari così come sono se nessun errore o visualizzare un messaggio di errore personalizzato in caso di problemi:

import React, { lazy, Suspense } from 'react';

const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));

const renderLoader = () => <p>Loading</p>;

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = {hasError: false};
  }

  static getDerivedStateFromError(error) {
    return {hasError: true};
  }

  render() {
    if (this.state.hasError) {
      return <p>Loading failed! Please reload.</p>;
    }

    return this.props.children;
  }
}

const DetailsComponent = () => (
  <ErrorBoundary>
    <Suspense fallback={renderLoader()}>
      <AvatarComponent />
      <InfoComponent />
      <MoreInfoComponent />
    </Suspense>
  </ErrorBoundary>
)

Conclusione

Se non sai da dove iniziare ad applicare la suddivisione del codice alla tua reazione segui questi passaggi:

  1. Inizia a livello di percorso. I percorsi sono il modo più semplice per identificare i punti la tua applicazione che può essere suddivisa. La Documentazione relativa alle reazioni mostra come può essere utilizzato Suspense insieme a react-router.
  2. Identifica tutti i componenti di grandi dimensioni di una pagina del sito che vengono visualizzati solo determinate interazioni dell'utente (ad esempio i clic su un pulsante). Suddivisione minimizzeranno i payload JavaScript.
  3. Valuta la possibilità di suddividere qualsiasi altro elemento fuori schermo e non essenziale per il utente.