W tym laboratorium programistycznym zwiększ wydajność tej aplikacji, usuwając nieużywane i niepotrzebne zależności.
Zmierz odległość
Przed wprowadzeniem optymalizacji warto najpierw sprawdzić, jak działa witryna.
- Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację. Następnie kliknij Pełny ekran .
Kliknij ulubionego kotka. W tej aplikacji jest używana Baza danych czasu rzeczywistego Firebase, dlatego wynik jest aktualizowany w czasie rzeczywistym i synchronizowany z każdym innym użytkownikiem aplikacji. 🐈
- Aby otworzyć Narzędzia dla programistów, naciśnij `Control+Shift+J` (lub `Command+Option+J` na Macu).
- Kliknij kartę Sieć.
- Zaznacz pole wyboru Disable cache (Wyłącz pamięć podręczną).
- Przeładuj aplikację.
Ładowanie tej prostej aplikacji wymaga przesyłania prawie 1 MB kodu JavaScriptu.
Sprawdź ostrzeżenia dotyczące projektu w Narzędziach deweloperskich.
- Kliknij kartę Konsola.
- Upewnij się, że opcja
Warnings
jest włączona w menu poziomów obok wejściaFilter
.
- Sprawdź wyświetlone ostrzeżenie.
Firebase, która jest jedną z bibliotek używanych w tej aplikacji, zachowuje się jak Samarytanin, wyświetlając ostrzeżenie, aby poinformować deweloperów, że nie powinni importować całego pakietu, tylko używane komponenty. Innymi słowy, w tej aplikacji są nieużywane biblioteki, które można usunąć, aby przyspieszyć jej wczytywanie.
Są też przypadki, gdy używana jest dana biblioteka, ale może istnieć prostsza alternatywa. W dalszej części tego samouczka omawiamy usuwanie niepotrzebnych bibliotek.
Analizowanie pakietu
Aplikacja ma 2 główne zależności:
- Firebase: platforma, która udostępnia wiele przydatnych usług dla aplikacji na iOS, Androida i internet. W tym przypadku Baza danych czasu rzeczywistego służy do przechowywania i synchronizowania informacji o każdym kocie w czasie rzeczywistym.
- Moment.js: biblioteka narzędziowa ułatwiająca obsługę dat w JavaScript. Data urodzenia każdego kociaka jest przechowywana w bazie danych Firebase, a do obliczenia jego wieku w tygodniach służy parametr
moment
.
Jak to możliwe, że 2 zależności zajmują prawie 1 MB? Jednym z powodów jest to, że każda zależność może mieć swoje własne zależności, więc jeśli weźmiemy pod uwagę każdą głębokość/gałąź „drzewa” zależności, liczba zależności będzie znacznie większa niż 2. Aplikacja może stosunkowo szybko stać się duża, jeśli zawiera wiele zależności.
Przeanalizuj pakiet, aby lepiej zrozumieć, co się dzieje. Dostępnych jest wiele narzędzi stworzonych przez społeczność, które mogą Ci w tym pomóc, np. webpack-bundle-analyzer
.
Pakiet tego narzędzia jest już zawarty w aplikacji jako devDependency
.
"devDependencies": {
//...
"webpack-bundle-analyzer": "^2.13.1"
},
Oznacza to, że można go używać bezpośrednio w pliku konfiguracji webpacka.
Zaimportuj go na samym początku webpack.config.js
:
const path = require("path");
//...
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
Teraz dodaj go jako wtyczkę na samym końcu pliku w tablicy plugins
:
module.exports = {
//...
plugins: [
//...
new BundleAnalyzerPlugin()
]
};
Po ponownym załadowaniu aplikacji zamiast samej aplikacji powinna się wyświetlić wizualizacja całego pakietu.
Nie jest to tak urocze jak oglądanie kotków 🐱, ale i tak jest bardzo pomocne. Po najechaniu kursorem na dowolny pakiet możesz zobaczyć jego rozmiar w 3 sposoby:
Rozmiar statystyk | Rozmiar przed zminimalizowaniem lub skompresowaniem. |
---|---|
Rozmiar po przeanalizowaniu | Rozmiar rzeczywistego pakietu w pakiecie po jego skompilowaniu. Wersja 4 webpacka (która jest używana w tej aplikacji) automatycznie kompresuje skompilowane pliki, dlatego ich rozmiar jest mniejszy niż rozmiar statystyczny. |
Rozmiar skompresowany | Rozmiar pakietu po skompresowaniu go za pomocą kodowania gzip. Ten temat jest omówiony w osobnym przewodniku. |
Narzędzie webpack-bundle-analyzer ułatwia identyfikowanie nieużywanych lub niepotrzebnych pakietów, które stanowią duży odsetek pakietu.
Usuwanie nieużywanych pakietów
Wizualizacja pokazuje, że pakiet firebase
składa się z wiele więcej niż tylko z bazy danych. Obejmuje ona dodatkowe pakiety, takie jak:
firestore
auth
storage
messaging
functions
To świetne usługi oferowane przez Firebase (więcej informacji znajdziesz w dokumentacji), ale żadna z nich nie jest używana w aplikacji, więc nie ma powodu, aby importować je wszystkie.
Aby ponownie zobaczyć aplikację, cofnij zmiany w webpack.config.js
:
- Usuń
BundleAnalyzerPlugin
z listy wtyczek:
plugins: [
//...
new BundleAnalyzerPlugin()
];
- Teraz usuń nieużywany import z góry pliku:
const path = require("path");
//...
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
Aplikacja powinna się teraz wczytać normalnie. Zmień src/index.js
, aby zaktualizować importy z Firebase.
import firebase from 'firebase';
import firebase from 'firebase/app';
import 'firebase/database';
Gdy aplikacja zostanie ponownie załadowana, ostrzeżenie w narzędziach deweloperskich nie będzie się już wyświetlać. W panelu Sieć w DevTools widać też znaczne zmniejszenie rozmiaru pakietu:
Usunięto ponad połowę rozmiaru pakietu. Firebase udostępnia wiele różnych usług i daje deweloperom możliwość uwzględnienia tylko tych, których rzeczywiście potrzebują. W tej aplikacji do przechowywania i synchronizowania wszystkich danych używana była tylko usługa firebase/database
. Import firebase/app
, który konfiguruje interfejs API dla każdej z usług, jest zawsze wymagany.
Wiele innych popularnych bibliotek, np. lodash
, pozwala deweloperom selektywnie importować różne części pakietów. Bez większego wysiłku możesz zaktualizować importowane w aplikacji biblioteki, aby zawierały tylko te, których używasz. Może to znacznie poprawić wydajność.
Chociaż rozmiar pakietu został znacznie zmniejszony, nadal jest jeszcze wiele do zrobienia. 😈
Usuwanie niepotrzebnych pakietów
W odróżnieniu od Firebase importowanie części biblioteki moment
nie jest tak łatwe, ale może da się ją całkowicie usunąć?
Data urodzin każdego uroczego kociaka jest przechowywana w formie Unix (w milisekundach) w bazie danych Firebase.
To sygnatura czasowa określonej daty i godziny wyrażona jako liczba milisekund, które upłynęły od 1 stycznia 1970 r., godz. 00:00 czasu UTC. Jeśli bieżąca data i godzina mogą być obliczane w tym samym formacie, można stworzyć małą funkcję, która pozwoli znaleźć wiek każdego kociaka w tygodniach.
Jak zawsze, podczas wykonywania tych czynności nie kopiuj i wklej tekstu. Najpierw usuń moment
z importowanych danych w src/index.js
.
import firebase from 'firebase/app';
import 'firebase/database';
import * as moment from 'moment';
W naszej bazie danych jest odbiorca zdarzeń Firebase, który obsługuje zmiany wartości:
favoritesRef.on("value", (snapshot) => { ... })
Powyżej tego zdefiniuj małą funkcję, która oblicza liczbę tygodni od danej daty:
const ageInWeeks = birthDate => {
const WEEK_IN_MILLISECONDS = 1000 * 60 * 60 * 24 * 7;
const diff = Math.abs((new Date).getTime() - birthDate);
return Math.floor(diff / WEEK_IN_MILLISECONDS);
}
W tej funkcji różnica w milisekundach między bieżącą datą i czasem (new Date).getTime()
a datą urodzenia (argument birthDate
, podany już w milisekundach) jest obliczana i dzielona przez liczbę milisekund w jednym tygodniu.
W reszcie wszystkie wystąpienia funkcji moment
można usunąć w słuchaczu zdarzeń, korzystając z tej funkcji:
favoritesRef.on("value", (snapshot) => { const { kitties, favorites, names, birthDates } = snapshot.val(); favoritesScores = favorites; kittiesList.innerHTML = kitties.map((kittiePic, index) => {const birthday = moment(birthDates[index]);return ` <li> <img src=${kittiePic} onclick="favKittie(${index})"> <div class="extra"> <div class="details"> <p class="name">${names[index]}</p><p class="age">${moment().diff(birthday, 'weeks')} weeks old</p><p class="age">${ageInWeeks(birthDates[index])} weeks old</p> </div> <p class="score">${favorites[index]} ❤</p> </div> </li> `}) });
Ponownie załaduj aplikację i jeszcze raz spójrz na panel Sieć.
Rozmiar naszego pakietu zmniejszył się o ponad połowę.
Podsumowanie
Po wykonaniu tego ćwiczenia powinieneś/powinnaś już wiedzieć, jak analizować konkretne pakiety i dlaczego warto usuwać nieużywane lub niepotrzebne pakiety. Zanim zaczniesz optymalizować aplikację za pomocą tej metody, warto wiedzieć, że w przypadku większych aplikacji może to być znacznie bardziej skomplikowane.
Jeśli chodzi o usuwanie nieużywanych bibliotek, spróbuj się dowiedzieć, które części pakietu są używane, a które nie. Jeśli jakiś pakiet wygląda tajemniczo i wygląda na to, że nigdzie nie jest używany, cofnij się i sprawdź, których zależności najwyższego poziomu mogą go potrzebować. Spróbuj znaleźć sposób na ich rozdzielenie.
Jeśli chodzi o usuwanie zbędących bibliotek, sprawa może być nieco bardziej skomplikowana. Ważne jest, aby ściśle współpracować z zespołem i sprawdzać, czy można uprościć niektóre części kodu źródłowego. Usunięcie moment
w tym
założeniu może wydawać się właściwym rozwiązaniem, ale co, jeśli trzeba uwzględnić strefy czasowe i różne lokalizacje? A co, jeśli manipulacja datą jest bardziej skomplikowana? Podczas manipulowania i analizowania dat i godzin mogą pojawić się problemy, ale biblioteki takie jak moment
i date-fns
znacznie to upraszczają.
Wszystko ma swoje wady i zalety, dlatego warto ocenić, czy wdrożenie niestandardowego rozwiązania jest warte wysiłku i skomplikowania, zamiast polegania na bibliotece innej firmy.