Opóźnione ładowanie komponentów Reacta
Jakiś czas temu React wypuścił wersję 16.6.0, która zawiera nową funkcję upraszczającą użycie opóźnionego ładowania (lazy loading) bez pomocy zewnętrznych bibliotek. Rzućmy okiem na to, jak można ją wykorzystać, aby poprawić wydajność i zapewnić lepsze doświadczenie dla użytkowników. Przy budowaniu za pomocą komponentów przydatne jest zorganizowanie ich w kolekcję za pomocą takich narzędzi jak Bit. Możesz potem udostępniać swoje komponenty oraz z nich korzystać w dowolnej aplikacji, aby przyspieszyć programowanie i sprawić, żeby Twój kod był bardziej DRY. Oto i on.
Czym jest react.lazy()
Jest to nowa funkcja, która pozwala na opóźnione ładowanie komponentów Reacta dzięki dzieleniu kodu bez pomocy dodatkowych bibliotek. Opóźnione ładowanie to technika renderowania potrzebnych lub krytycznych elementów interfejsu użytkownika w pierwszej kolejności, a następnie ściąganie w tle elementów mniej ważnych, już po wyrenderowaniu działającego i internaktywnego UI.
Funkcja ta jest teraz w pełni zintegrowana z biblioteką reacta. Wcześniej, aby to osiągnąć, używaliśmy react-loadable
, ale w samym React mamy react.lazy()
.
Suspense
Suspense jest komponentem wymaganym przez funkcję lazy
, którego używa się do opakowywania “leniwych” komponentów. Jeden komponent Suspense może opakować wiele “leniwych” komponentów. Przyjmuje on właściwość zawierającą elementy Reacta, które chcesz wyświetlić w czasie, gdy następuje opóźnione ładowanie komponentu.
Dlaczego opóźnione ładowanie (oraz Suspense) są istotne
Po pierwsze, bundling polega na ułożeniu kodu w odpowiedniej kolejności, by zadziałał jako jeden kawałek JS, gdy przekażemy go do przeglądarki. Jednak wraz z rozwojem aplikacji zauważamy, że pakiet może rozrosnąć się do rozmiarów, które są problematyczne. Może to szybko sprawić, że ciężko będzie korzystać z aplikacji ze względu na powolne ładowanie. Dzięki podziałowi kodu pierwotny pakiet można podzielić na mniejsze części, z których najpierw ładuje się najważniejszą, a następnie pozostałe (używamy tutaj opóźnionego ładowania). Ponadto, aplikacje powinniśmy tworzyć również dla użytkowników używających wolnych połączeń z internetem (np. korzystajacych z internetu mobilnego).
Powinniśmy mieć możliwość kontrolowania doświadczenia użytkownika, nawet w momencie, w którym dopiero ładujemy zasoby do DOM.
Jak zacząć
Zgodnie z oficjalną dokumentacją Reacta, webpack będzie od razu gotowy do użycia, jeżeli skorzystasz z:
- CRA (create react app)
- Next js
- Gatsby
Jeśli nie, to musisz samodzielnie skonfigurować proces tworzenia paczek. Zobacz poradniki z oficjalnej dokumentacji webpacka (Installation oraz Getting Started).
Wersja demonstracyjna
Chcemy teraz stworzyć aplikację Reacta, która wyświetla nazwy i liczbę albumów artystów MTV Base z 2019 roku, korzystając z narzędzia create-react-app
. Następnie zaimplementujemy opóźnione ładowanie z suspense. Uprościłem nieco create-react-app
i zbudowałem prosty komponent, którego tutaj użyjemy.
- Sklonuj repozytorium
- Rozpakuj plik i otwórz terminal
- Zainstaluj moduły node'a projektu w katalogu głównym powstałym po rozpakowaniu plików, za pomocą takiej komendy:
$ sudo npm install
- Stwórz serwer lokalny z poniższym poleceniem:
$ sudo npm start
Przykładowa aplikacja
Oto nasza aplikacja. Jeśli skopiowaliście repozytorium, to zobaczycie, że dane artystów są wewnątrz aplikacji i stąd są ładowane.
Możesz też stworzyć swoją własną aplikację i wprowadzić poniższe zmiany. BTW, folder src aplikacji powinien wyglądać następująco:
Artists.js
import React from ‘react’;
import ‘./App.css’;
import artists from “./store”;
export default function Artists(){
return (
<>
<h1>MTV Base Headline Artists 2019</h1>
{artists.map(artist =>(
<div id=”card-body” key={artist.id}>
<div className=”card”>
<h2>{artist.name}</h2>
<p>genre: {artist.genre}</p>
<p>Albums released: {artist.albums}</p>
</div>
</div>
))}
</>
);
}
Store.js
export default [
{
id: “1”,
name: “Davido”,
country: “Nigeria”,
genre: “Afro-Pop”,
albums: “2”
},
{
id: “2”,
name: “AKA”,
country: “South-Africa”,
genre: “Hip-Hop”,
albums: “4”
},
{
id: “3”,
name: “Seyi Shay”,
country: “Nigeria”,
genre: “R&B”,
albums: “2”
},
{
id: “4”,
name: “Sauti Sol”,
country: “Kenya”,
genre: “Soul”,
albums: “3”
}
];
Index.js
import React from ‘react’;
import ReactDOM from ‘react-dom’;
import ‘./index.css’;
import Artists from ‘./Artists’;
class App extends React.Component {
render(){
return(
<div className=”App”>
<Artists />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById(‘root’));
App.css
.App {
text-align: center;
}
h1 {
padding: 30px;
}
#card-body {
display: inline-flex;
padding: 10px;
margin: 30px 30px;
border: 5px solid rgb(93, 171, 207);
border-radius: 8px;
background: lightblue;
}
Zobaczmy teraz, jak używać react.lazy
i suspense do obsługi opóźnionego ładowania komponentu artist
.
- Przejdź do pliku
index.js
i zaimportujlazy
oraz suspense z Reacta w następujący sposób:
import { Suspense, lazy } from 'react';
- Aby wyrenderować import dynamiczny jako zwykły komponent, dokumentacja Reacta podaje następującą składnię użycia
react.lazy
:
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<OtherComponent />
</div>
);
}
- Próbując powyższego z naszym komponentem
Artists
, otrzymalibyśmy coś takiego:
const Artists = React.lazy(() => import('./Artists'));
function MyComponent() {
return (
<div>
<Artists />
</div>
);
}
Jeśli moduł zawierający Artists
nie zostanie załadowany do czasu wyrenderowania mojego komponentu, musimy, czekając na to, pokazać zawartość zastępczą. Może to być wskaźnik ładowania, uruchamiany przez komponent Suspense. Poniżej znajduje się składnia dodająca komponent suspense do react.lazy
:
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
Z naszym komponentem artist
, przybiera to następującą formę:
const Artists = React.lazy(() => import('./Artists'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<Artists />
</Suspense>
</div>
);
}
Gdy poskładamy wszystko do kupy, Twój plik index.js
powinien wyglądać następująco:
import React, { lazy, Suspense } from ‘react’;
import ReactDOM from ‘react-dom’;
import ‘./index.css’;
// import Artists from ‘./Artists’;
const Artists = lazy(() => import(‘./Artists’))
class App extends React.Component {
render(){
return(
<div className=”App”>
<Suspense fallback={<h1>Still Loading…</h1>}>
<Artists />
</Suspense>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById(‘root’));
Na Twoim localhoscie powinno to pójść tak szybko, że możesz nie być w stanie dostrzec pewnych zmian. Można jednak utworzyć helper opóźniający ładowanie lub zasymulować wolniejszą sieć, która byłaby w stanie dokładnie pokazać, jak zmiany zachodzą w milisekundach. Można to zrobić w następujący sposób:
- Otwórz dev tools w swojej przeglądarce
- Wybierz zakładkę network
- Kliknij zakładkę online, która znajduje się po prawej stronie, aby rozwinąć presety
- Wybierz Fast G3
Dev Tools
Możesz teraz odświeżyć przeglądarkę i obserwować opóźnione ładowanie w akcji.
Nadal się ładuje.
Wiele “leniwych” komponentów
Dodajmy szybko mały komponent, który renderuje nagłówek, i zobaczmy, jak funkcja react.lazy obsługuje go tylko z jednym komponentem Suspense.
Utwórz plik performers.js
w folderze src
i dodaj poniższy kod:
import React from ‘react’;
import ‘./App.css’;
export default function Performers(){
return (
<>
<h2>These are the MTV Base Headline Artists...</h2>
</>
);
}
Następnie dodaj linijkę z leniwym komponentem w index.js
, który powinien wyglądać teraz tak:
import React, { lazy, Suspense } from ‘react’;
import ReactDOM from ‘react-dom’;
import ‘./index.css’;
const Artists = lazy(() => import(‘./Artists’))
const Performers = lazy(() => import(‘./Performers’))
class App extends React.Component {
render(){
return(
<div className=”App”>
<Suspense fallback={<h1>Still Loading…</h1>}>
<Artists />
<Performers />
</Suspense>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById(‘root’));
Dwa komponenty używające opóźnionego ładowania pojawiają się po wyrenderowaniu elementu placeholder z Suspense.
Dwa komponenty lazy załadowane wewnątrz jednego komponentu suspense
Zupełnie się to różni od loadable
, który musiałby renderować element wczytywania dla każdego komponentu osobno.
Ważne!
Funkcje react.lazy
i suspense nie działają jeszcze w przypadku renderowania po stronie serwera. Jeśli chcesz rozdzielić kod w aplikacji renderowanej przez serwer, to wysoce zalecany jest komponent loadable, ponieważ posiada on niezły przewodnik na temat dzielenia pakietów przy renderowaniu po stronie serwera.
Podsumowanie
Zobaczyliśmy, jak zacząć korzystać z komponentów "leniwych" oraz Suspense, dzięki którym można użyć opóźnionego ładowania w React. Powyższy przykład jest naprawdę prosty w porównaniu z wieloma innymi możliwościami, jakie dają te nowe funkcje. Miłego kodowania!