Nigdy nie musisz wysyłać użytkownikom więcej kodu, niż jest to konieczne, więc podziel pakiety, aby nigdy tego nie osiągnąć.
Metoda React.lazy
ułatwia podział kodu aplikacji React na poziomie komponentu za pomocą importu dynamicznego.
import React, { lazy } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const DetailsComponent = () => (
<div>
<AvatarComponent />
</div>
)
Dlaczego to takie przydatne?
Duża aplikacja React zazwyczaj składa się z wielu komponentów, metod użytkowych i bibliotek zewnętrznych. Jeśli nie starasz się wczytywać poszczególnych części aplikacji tylko wtedy, gdy są one potrzebne, wysyłamy użytkownikom pojedynczy, duży pakiet kodu JavaScript zaraz po wczytaniu pierwszej strony. Może to znacznie wpłynąć na wydajność strony.
Funkcja React.lazy
zapewnia wbudowaną sposób rozdzielania komponentów aplikacji na osobne fragmenty JavaScriptu, które wymagają minimalnego nakładu pracy. Po połączeniu go z komponentem Suspense
możesz zająć się stanami wczytywania.
Suspens
Problem z wysłaniem dużego ładunku JavaScript do użytkowników polega na długim czasie potrzebnym na wczytanie strony, zwłaszcza w przypadku słabszych urządzeń i połączeń sieciowych. Dlatego właśnie podział kodu i leniwe ładowanie są tak przydatne.
Zawsze jednak występują niewielkie opóźnienia, które muszą wystąpić podczas pobierania przez sieć komponentu z podziałem kodu, dlatego ważne jest, aby stan wczytywania był przydatny. Użycie React.lazy
z komponentem 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 dowolnego komponentu React jako stanu wczytywania. Poniższy przykład pokazuje, jak to działa.
Awatar jest renderowany dopiero po kliknięciu przycisku i wysyłaniu żądania pobrania kodu niezbędnego do pobrania kodu AvatarComponent
.
W międzyczasie wyświetlany jest komponent zastępczego wczytywania.
Kod w elemencie AvatarComponent
jest w tym przypadku niewielki, dlatego ikona wczytywania wyświetla się tylko przez krótki czas. Wczytywanie większych komponentów może potrwać znacznie dłużej, zwłaszcza w przypadku słabych połączeń sieciowych.
Aby lepiej zademonstrować, jak to działa:
- Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację, a potem 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 ma domyślnie wartość Bez ograniczania. Wybierz Szybka 3G.
- Kliknij przycisk Kliknij mnie w aplikacji.
Wskaźnik wczytywania będzie się teraz dłużej wyświetlać. Zwróć uwagę, że cały kod, który tworzy AvatarComponent
, jest pobierany jako oddzielny fragment.
Zawieszanie wielu komponentów
Kolejną funkcją Suspense
jest możliwość zawieszenia wczytywania wielu komponentów, nawet jeśli są one leniwe.
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 skuteczny sposób na opóźnienie renderowania wielu komponentów w ramach pokazywania tylko jednego stanu wczytywania. Gdy wszystkie komponenty zakończą pobieranie, użytkownik zobaczy je wszystkie w tym samym czasie.
Możesz to zobaczyć, jeśli umieszczone są następujące elementy:
Bez niego łatwo może pojawić się problem z przesuniętym ładowaniem lub wczytywaniem różnych elementów interfejsu jeden po drugim, które mają własny wskaźnik ładowania. Może to sprawić, że wrażenia użytkownika będą bardziej irytujące.
Postępowanie w przypadku błędów wczytywania
Suspense
umożliwia wyświetlanie tymczasowego stanu wczytywania, gdy żądania sieciowe są wysyłane. A co, jeśli żądania sieciowe
z jakiegoś powodu nie powiodą się? Być może jesteś offline lub Twoja aplikacja internetowa próbuje leniwie wczytywać adres URL z wersją, który jest nieaktualny i nie jest już dostępny po ponownym wdrożeniu serwera.
React ma standardowy wzorzec, który pozwala na płynną obsługę tego typu błędów wczytywania: użycie granicy błędu. Jak opisano w dokumentacji, każdy komponent React może służyć jako granica błędu, jeśli implementuje jedną (lub obie) metody cyklu życia static getDerivedStateFromError()
albo componentDidCatch()
.
Aby wykrywać i radzić sobie z błędami leniwego wczytywania, możesz opakować komponent Suspense
komponentami nadrzędnymi, które służą jako granica błędu. W metodzie render()
na granicy błędu możesz wyrenderować elementy podrzędne w takiej postaci, w jakiej nie ma błędów, lub wyświetlić niestandardowy komunikat o błędzie, jeśli coś pójdzie 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ąć dzielić kod w aplikacji React, wykonaj te czynności:
- Zacznij od poziomu trasy. Trasy to najprostszy sposób identyfikowania punktów aplikacji, które można podzielić. W dokumentach React znajdziesz informacje o tym, jak używać
Suspense
w połączeniu zreact-router
. - Zidentyfikuj na stronie w witrynie wszystkie duże komponenty, które renderują się tylko w przypadku określonych interakcji użytkownika (np. kliknięcia przycisku). Rozdzielenie tych komponentów zminimalizuje ładunki JavaScript.
- Rozważ podzielenie wszystkiego, co nie jest istotne dla użytkownika i nie jest istotne dla użytkownika.