Spis treści
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:
Widać też, że 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:
A ilość pobranego kodu JS zmniejszyła się o 40 kb:
Kod załadował się dopiero po kliknięciu przycisku:
Wtedy również załadowały się style komponentu:
Jeśli zysk rzędu 40 kb wydaje Ci się nieduży pamiętaj o dwóch rzeczach:
- Używamy wersji niezminifikowanej, stąd 40kb jakie wniósł moment.js to 5% rozmiaru, po minifikacji będzie to więcej
- 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.