React lazy loading – sprawdź co zyskasz!

Spis treści

  1. Wprowadzenie
  2. Przykład React lazy loading
    1. Opis
    2. Kod przykładu
      1. Szkielet aplikacji
      2. Wersja ze standardowym importem
      3. Wersja z importem przez lazy
    3. Kod przykładu React lazy na Github
    4. Klikalny przykład React lazy na Github Pages
  3. Podsumowanie

Wprowadzenie

Czy zastanawiało Cię kiedyś, jak wiele kodu z Twojej aplikacji nigdy nie zostanie przez część klientów użyte? Zdarzyło Ci się może zastanawiać, jak wiele z CSSów które piszesz zobaczy tylko jakiś procent użytkowników? Lub też wiesz, że pewnych elementów używa tylko pewien procent użytkowników?
Jeśli te założenia są prawdziwe w Twoim projekcie, możesz zastanowić się czy nie warto zaimplementować ładowania dynamicznego za pomocą React lazy – zwłaszcza jeśli bibliotek czy innych ciężkich elementów Twoja aplikacja używa tylko w pewnych kontekstach.

Przykład React lazy loading

Opis

Napiszmy prosty projekt w którym porównamy ile kodu pobierane będzie na start aplikacji bez dynamicznego ładowaniem i z dynamicznym ładowaniem.

Sprawdzimy czy aplikacja załaduje style CSS i bibliotekę moment.js dopiero w momencie, gdy będą potrzebne.

Aplikacja załaduje te elementy po kliknięciu w przycisk. Dla styli użyjemy CSS Modules, wspieranych domyślnie w aplikacjach utworzonych przy użyciu create-react-app. Opisuję je, wraz z biblioteką React CSS Modules oraz alternatywą w postaci pluginu babel-plugin-react-css-modules, w artykule Poznaj 5 Sposobów Stylowania Komponentów React w 2020:

Moment.js jest już w trybie utrzymaniowym, stąd może wynikać chęć by do czasu refaktoryzacji danego fragmentu kodu ładować go tylko gdy naprawdę jest potrzebny.

Kod przykładu

Szkielet aplikacji

Aplikacja zawierać będzie przycisk, po kliknięciu którego pokaże się komponent mający zdefiniowane style CSS i używający biblioteki moment.js:

function App() {
  const [load, setLoad] = useState(false)

  return (
    <div style={{padding: 50}}>
      <button onClick={() => setLoad(true)}>
        Load component with styles and moment.js
      </button>
      {
        load && (
          <Suspense fallback={<p>Loading...</p>}>
            <Lazy />
          </Suspense>
        )
      }
    </div>
  );
}

Kod komponentu Lazy zawiera style i ładowanie biblioteki:

import moment from "moment";
import styles from './Lazy.module.css';

const Lazy = () => (
  <p className={styles.lazy}>Text with styles, current date: {moment(new Date()).format()}</p>
);

export default Lazy;

Wersja ze standardowym importem

Kluczowa różnica polega na sposobie zaimportowania komponentu Lazy.

Jeżeli w App.js zaimportujemy go zwyczajnie:

import Lazy from './Lazy';

Wtedy mimo, że komponent nie jest jeszcze widoczny widzimy, że załadowały się jego style:

Załadowane style dla niewidocznego komponentu Lazy
Załadowane style dla niewidocznego komponentu Lazy

Widać też, że cały kod JS ładuje się od razu:

Bez użycia lazy cały kod JS ładuje się od razu
Bez użycia lazy cały kod JS ładuje się od razu

Wersja z importem przez lazy

Jeżeli użyjemy importu dynamicznego:

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

Wtedy możemy się przekonać, że na start żadne style nie zostały załadowane:

Przy użyciu React lazy nie ma zaimportowanych stylów
Przy użyciu React lazy nie ma zaimportowanych stylów

A ilość pobranego kodu JS zmniejszyła się o 40 kb:

Kod komponentu i biblioteki nie załadował się ponieważ nie jest potrzebny
Kod komponentu i biblioteki nie załadował się ponieważ nie jest potrzebny

Kod załadował się dopiero po kliknięciu przycisku:

Doładowanie kodu za pomocą React lazy dopiero w momencie gdy jest potrzebny
Doładowanie kodu za pomocą React lazy dopiero w momencie gdy jest potrzebny

Wtedy również załadowały się style komponentu:

Doładowanie stylów komponentu za pomocą React lazy dopiero wtedy gdy są potrzebne
Doładowanie stylów komponentu za pomocą React lazy dopiero wtedy gdy są potrzebne

Jeśli zysk rzędu 40 kb wydaje Ci się nieduży pamiętaj o dwóch rzeczach:

  1. Używamy wersji niezminifikowanej, stąd 40kb jakie wniósł moment.js to 5% rozmiaru, po minifikacji będzie to więcej
  2. W rzeczywistej aplikacji za pomocą lazy możemy wyłączać całe ogromne moduły – jeżeli masz w swojej aplikacji np moduł edycji obrazu, możesz nie ładować skomplikowanych filtrów podczas ładowania aplikacji.

Kod przykładu React lazy na Github

Pełny kod przykładu znajdziesz pod adresem:

https://github.com/radek-anuszewski/react-lazy-loading-demo

Klikalny przykład React lazy na Github Pages

Klikalny przykład znajdziesz pod adresem:

https://radek-anuszewski.github.io/react-lazy-loading-demo/

Podsumowanie

Im większa aplikacja, tym bardziej spektakularne korzyści z lazy loadingu może czerpać końcowy użytkownik. Mniej kodu JS do pobrania to mniej kodu JS do parsowania i kompilowania, mniej kodu CSS to mniej obliczeń koniecznych do zarządzania stylami. Więc im bardziej w naszym kodzie widzimy granice, które możemy rysować pomiędzy funkcjonalnościami tym bardziej opłaca się skorzystać z możliwości lazy loadingu oferowanego przez React.