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. 🐈
- Naciśnij „Control + Shift + J” (lub „Command + Option + J” na Macu), aby otworzyć Narzędzia deweloperskie.
- Kliknij kartę Sieć.
- Zaznacz pole wyboru Disable cache (Wyłącz pamięć podręczną).
- Ponownie załaduj aplikację.
Ładowanie tej prostej aplikacji wymaga przesłania prawie 1 MB kodu JavaScriptu.
Przejrzyj ostrzeżenia dotyczące projektu w Narzędziach deweloperskich.
- Kliknij kartę Konsola.
- Sprawdź, czy opcja
Warnings
jest włączona w menu poziomów obok pola wejściowegoFilter
.
- 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. Inaczej mówiąc, istnieją nieużywane biblioteki, które można usunąć w aplikacji, aby przyspieszyć jej wczytywanie.
Są też przypadki, gdy używana jest dana biblioteka, ale może istnieć prostsza alternatywa. Koncepcję usuwania zbędnych bibliotek omawiamy w dalszej części tego samouczka.
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. Tutaj jej baza danych czasu rzeczywistego służy do przechowywania i synchronizowania informacji o poszczególnych kociach 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.
Przeprowadź analizę działania usługi tworzącej pakiet, aby uzyskać lepszy obraz tego, 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 pakietu internetowego.
Zaimportuj go na samym początku elementu 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 powinna pojawić się wizualizacja całego pakietu, a nie samej aplikacji.
Nie jest to tak urocze jak kotki 🐱, 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 przetworzeniu | 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 wspaniałe 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 teraz załadować się 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 znacznie się zmniejszył, nadal jest sporo pracy 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 czasu uniksowego (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 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, postaraj się nie kopiować i wklejać treści, które widzisz tutaj. Zacznij od usunięcia moment
z importów w src/index.js
.
import firebase from 'firebase/app';
import 'firebase/database';
import * as moment from 'moment';
W naszej bazie danych dostępny jest detektor 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 odbiorniku zdarzeń można też usunąć wszystkie wystąpienia funkcji moment
, korzystając z tego kodu:
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ż dobrze rozumieć, jak analizować konkretny pakiet 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 odłączenie.
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.