Podział kodu za pomocą React.lazy i Susense

Nigdy nie musisz wysyłać użytkownikom więcej kodu, niż jest to konieczne. Podziel pakiety, aby mieć pewność, że nigdy tak się nie stanie.

Metoda React.lazy ułatwia podział kodu aplikacji React na na poziomie komponentu za pomocą importu dynamicznego.

import React, { lazy } from 'react';

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

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

Dlaczego to jest przydatne?

Duża aplikacja React składa się zwykle z wielu komponentów, i biblioteki innych firm. Jeśli użytkownik nie spróbuje wczytać z różnych części aplikacji tylko wtedy, gdy są potrzebne: pojedynczy, duży pakiet JavaScript jest wysyłany do użytkowników zaraz po wczytaniu przez nich pierwszej strony. Może to znacząco wpłynąć na wydajność strony.

Funkcja React.lazy to wbudowany sposób rozdzielania komponentów w argumencie do tworzenia oddzielnych fragmentów JavaScriptu przy niewielkich nakładach pracy. Dostępne opcje Następnie zadbaj o stany wczytywania, gdy połączysz go z interfejsem Suspense .

Suspens

Problem z wysłaniem do użytkowników dużego ładunku JavaScriptu to długość Czas potrzebny na załadowanie strony, zwłaszcza na słabszych urządzeniach i połączeniami sieciowymi. Właśnie dlatego podział kodu i leniwe ładowanie jest bardzo przydatna.

Jednak użytkownicy zawsze będą musieli korzystać z niewielkiego opóźnienia komponent podziału kodu jest odczytywany przez sieć, więc ważne jest, wyświetlają przydatne informacje o stanie wczytywania. Używanie React.lazy z Suspense pomaga rozwiązać ten problem.

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

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

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

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

Suspense akceptuje komponent fallback, który umożliwia wyświetlanie dowolnej reakcji jako stan wczytywania. Poniższy przykład pokazuje, jak to działa. Awatar jest wyświetlany tylko po kliknięciu przycisku, gdy użytkownik poprosi o niego. a następnie uzyskać kod niezbędny do zawieszenia konta AvatarComponent. Do tego czasu wyświetlany jest komponent wczytywania zastępczego.

Tutaj kod tworzący AvatarComponent jest mały, Dlaczego ikona wczytywania wyświetla się tylko przez krótki czas? Większy Ładowanie komponentów może zająć dużo więcej czasu, zwłaszcza na urządzeniach słabe połączenia sieciowe.

Aby lepiej zademonstrować, jak to działa:

  • Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację. Następnie naciśnij Pełny ekran pełny ekran
  • Naciśnij „Control Shift J” (lub „Command Option J” na Macu), aby otworzyć Narzędzia deweloperskie.
  • Kliknij kartę Sieć.
  • Kliknij menu Ograniczanie, które jest domyślnie ustawione na Bez ograniczania. Wybierz Szybka sieć 3G.
  • Kliknij przycisk Kliknij mnie w aplikacji.

Wskaźnik wczytywania będzie wyświetlał się dłużej. Zwróć uwagę, że cały kod , z którego korzysta AvatarComponent, jest pobierany jako osobny fragment.

Panel sieci w Narzędziach deweloperskich z widocznym pobieranym plikiem chunk.js

Zawieszanie wielu komponentów

Inną cechą usługi Suspense jest to, że pozwala ona zawiesić z wczytywania komponentów, nawet jeśli wszystkie są ładowane leniwie.

Na przykład:

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>
)

Jest to niezwykle przydatny sposób opóźnienia renderowania wielu komponentów, który pokazuje tylko jeden stan wczytywania. Gdy wszystkie komponenty zostaną zakończone pobierania, użytkownik może zobaczyć je wszystkie wyświetlone w tym samym czasie.

Możesz zobaczyć to w tym przykładzie:

Bez niego łatwo napotkać problem wczytywania opóźnionego lub różne części interfejsu użytkownika wczytujące się jeden po drugim, każdy z własnym wskaźnik wczytywania. Może to sprawić, że wrażenia użytkowników będą bardziej przykuwające uwagę.

Postępowanie w przypadku błędów wczytywania

Suspense umożliwia wyświetlanie tymczasowego stanu wczytywania podczas korzystania z sieci i wysyłania żądań w całości. Co się jednak stanie, jeśli te żądania sieciowe nie zostaną zrealizowane Jakiś powód? Być może jesteś offline lub aplikacja internetowa próbuje leniwe ładowanie adresu URL z wersjami która jest nieaktualna i nie jest już dostępna po ponownym wdrożeniu serwera.

React ma standardowy wzorzec do płynnej obsługi takich procesów. niepowodzenia: używa granicy błędu. Jak opisano w dokumentacji, każdy komponent React może służyć jako granica błędu, jeśli ma obu) metod cyklu życia static getDerivedStateFromError() lub componentDidCatch()

Aby wykrywać i rozwiązywać błędy leniwego ładowania, możesz opakować Suspense z komponentem nadrzędnym, który służy jako granica błędu. Wewnątrz metody render() granicy błędu, możesz renderować elementy podrzędne w takiej postaci, w jakiej są, jeśli brak błędów lub wyświetlenie niestandardowego komunikatu o błędzie, jeśli coś poszło nie tak:

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>
)

Podsumowanie

Jeśli nie masz pewności, gdzie zacząć stosować podział kodu w React aplikacji, wykonaj następujące czynności:

  1. Zacznij na poziomie trasy. Trasy to najprostszy sposób identyfikacji punktów które można podzielić. Dokumenty React jak używać Suspense razem z react-router
  2. Zidentyfikuj na stronie witryny duże komponenty, które są renderowane tylko określonych interakcji użytkownika (takich jak kliknięcie przycisku). Dzielę minimalizują ładunki JavaScript.
  3. Rozważ wydzielenie tych elementów, które są poza ekranem i nie są niezbędne użytkownika.