Dzięki tym ćwiczeniom z programowania możesz zwiększyć wydajność poniższej aplikacji przez usunięcie nieużywanych i niepotrzebnych zależności.
Zmierz odległość
Przed wprowadzeniem optymalizacji zawsze warto zacząć mierzyć skuteczność witryny.
- Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację, a potem Pełny ekran .
Śmiało, kliknij swojego ulubionego kota. W tej aplikacji używana jest baza danych czasu rzeczywistego Firebase, dlatego wynik jest aktualizowany w czasie rzeczywistym i synchronizowany z każdą inną osobą korzystającą z aplikacji. 🐈
- Naciśnij „Control + Shift + J” (lub „Command + Option + J” na Macu), aby otworzyć Narzędzia deweloperskie.
- Kliknij kartę Sieć.
- Zaznacz pole wyboru Wyłącz pamięć podręczną.
- Załaduj ponownie aplikację.
Aby wczytać tę prostą aplikację, wysyłamy prawie 1 MB kodu JavaScript.
Zapoznaj się z ostrzeżeniami dotyczącymi projektów w Narzędziach deweloperskich.
- Kliknij kartę Console (Konsola).
- Sprawdź, czy w menu poziomów obok danych wejściowych
Filter
włączona jest funkcjaWarnings
.
- Przeanalizuj wyświetlone ostrzeżenie.
Firebase, jedna z bibliotek używanych w tej aplikacji, jest dobrym samrytanem, ponieważ ostrzega programistów, aby nie importowali całego pakietu, a tylko używanych komponentów. Innymi słowy, istnieją nieużywane biblioteki, które można usunąć w tej aplikacji, aby przyspieszyć jej wczytywanie.
Zdarzają się również sytuacje, w których używana jest konkretna biblioteka, ale w których przypadku może być prostsza alternatywa. Kwestia usuwania niepotrzebnych bibliotek zostanie omówiona w dalszej części tego samouczka.
Analizuję pakiet
W aplikacji występują 2 główne zależności:
- Firebase: platforma oferująca wiele przydatnych usług na potrzeby aplikacji internetowych na iOS i Androida oraz aplikacji internetowych. Tutaj Baza danych czasu rzeczywistego jest wykorzystywana do przechowywania i synchronizowania informacji o każdym kotku w czasie rzeczywistym.
- Moment.js: biblioteka narzędziowa, która ułatwia obsługę dat w języku JavaScript. Data urodzenia każdego kotka jest przechowywana w bazie danych Firebase, a do obliczania jego wieku w tygodniach służy
moment
.
W jaki sposób tylko 2 zależności mogą zwiększyć rozmiar pakietu o prawie 1 MB? Jedną z powodów jest to, że każda zależność może z kolei mieć własne zależności, więc jeśli weźmie się pod uwagę każdą zależność „drzewa”, będzie o wiele więcej niż dwie. Gdy aplikacja zawiera wiele zależności, łatwo może szybko osiągnąć duże rozmiary.
Przeanalizuj usługę pakietów, aby lepiej zrozumieć, co się dzieje. Istnieje wiele różnych narzędzi społecznościowych, 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 konfiguracyjnym pakietu webpack.
Zaimportuj go na początku webpack.config.js
:
const path = require("path");
//...
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
Teraz dodaj je jako wtyczkę na końcu pliku w tablicy plugins
:
module.exports = {
//...
plugins: [
//...
new BundleAnalyzerPlugin()
]
};
Po ponownym załadowaniu aplikacji powinna wyświetlić się wizualizacja całego pakietu, a nie samej aplikacji.
Nie tak słodkie, jak oglądanie kocich kocich kotków, ale i tak niezwykle przydatne. Najechanie kursorem na dowolny pakiet powoduje wyświetlenie jego rozmiaru na 3 różne sposoby:
Rozmiar statystyk | Rozmiar przed minifikacją lub kompresją. |
---|---|
Przeanalizowane rozmiary | Rozmiar rzeczywistego pakietu w pakiecie po jego skompilowaniu. Wersja 4 pakietu internetowego (używanego w tej aplikacji) automatycznie minimalizuje skompilowane pliki, dlatego jest ona mniejsza niż rozmiar statystyk. |
Rozmiar pliku gzip | Rozmiar pakietu po skompresowaniu 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żą część pakietu.
Usuwanie nieużywanych pakietów
Wizualizacja pokazuje, że pakiet firebase
składa się z dużej ilości więcej niż tylko bazy danych. Obejmuje dodatkowe pakiety, takie jak:
firestore
auth
storage
messaging
functions
Wszystkie te usługi świadczone przez Firebase są niesamowite (więcej informacji znajdziesz w dokumentacji), ale żadna z nich nie jest używana w aplikacji, więc nie ma powodu, by importować je wszystkie.
Cofnij zmiany w webpack.config.js
, aby ponownie zobaczyć aplikację:
- Usuń
BundleAnalyzerPlugin
z listy wtyczek:
plugins: [
//...
new BundleAnalyzerPlugin()
];
- Teraz usuń nieużywany import u góry pliku:
const path = require("path");
//...
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
Aplikacja powinna się wczytać normalnie. Zmień src/index.js
, aby zaktualizować importy z Firebase.
import firebase from 'firebase';
import firebase from 'firebase/app';
import 'firebase/database';
Teraz po ponownym załadowaniu aplikacji ostrzeżenie dotyczące Narzędzi deweloperskich nie będzie się wyświetlać. Otwarcie panelu Sieć w Narzędziach deweloperskich pokazuje też niewielkie zmniejszenie rozmiaru pakietu:
Usunięto ponad połowę rozmiaru pakietu. Firebase oferuje wiele różnych usług i umożliwia deweloperom uwzględnianie tylko tych, które są rzeczywiście potrzebne. W tej aplikacji do przechowywania i synchronizowania wszystkich danych
używano tylko firebase/database
. Import danych firebase/app
, który konfiguruje platformę interfejsu API dla każdej z różnych usług, jest zawsze wymagany.
Wiele innych popularnych bibliotek, np. lodash
, pozwala też programistom na selektywne importowanie różnych części pakietów. Bez wykonywania wielu pracy zaktualizowanie importowanych bibliotek do aplikacji w taki sposób, aby zawierały tylko to, co jest używane, może znacznie poprawić wydajność.
Mimo że rozmiar pakietu został zmniejszony o nieco, jest jeszcze wiele do zrobienia. 😈
Usuwam niepotrzebne pakiety
W przeciwieństwie do Firebase importowanie części biblioteki moment
nie jest tak proste, a może można ją całkowicie usunąć.
Urodziny każdego uroczego kotka są przechowywane w formacie Unix (w milisekundach) w bazie danych Firebase.
Jest to sygnatura czasowa konkretnej daty i godziny wyrażona jako liczba milisekund, które upłynęły od godziny 00:00 czasu UTC 1 stycznia 1970 r. Jeśli aktualną datę i godzinę można obliczyć w tym samym formacie, prawdopodobnie da się utworzyć małą funkcję do określania wieku kotów w tygodniach.
Jak zawsze nie kopiuj i nie wklejaj treści w podany niżej sposób. Zacznij od usunięcia pola moment
z importów w src/index.js
.
import firebase from 'firebase/app';
import 'firebase/database';
import * as moment from 'moment';
Dostępny jest detektor zdarzeń Firebase, który obsługuje zmiany wartości w naszej bazie danych:
favoritesRef.on("value", (snapshot) => { ... })
Powyżej dodaj małą funkcję, która oblicza liczbę tygodni od podanej 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 między bieżącą datą i godziną (new Date).getTime()
a datą urodzenia (argument birthDate
, już wyrażona w milisekundach) jest obliczana i dzielona przez liczbę milisekund w ciągu jednego tygodnia.
Wszystkie wystąpienia moment
można też usunąć z detektora, 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> `}) });
Załaduj ponownie aplikację i jeszcze raz przyjrzyj się panelowi Network (Sieć).
Rozmiar naszego pakietu został ponownie zmniejszony o ponad połowę.
Podsumowanie
Dzięki temu ćwiczeniu w programowaniu dowiesz się, jak analizować poszczególne pakiety i dlaczego może to pomóc w usuwaniu nieużywanych lub niepotrzebnych pakietów. Zanim zaczniesz optymalizować aplikację za pomocą tej metody, pamiętaj, że w przypadku większych aplikacji może to być znacznie bardziej skomplikowane.
Jeśli chodzi o usuwanie nieużywanych bibliotek, sprawdź, które części pakietu są używane, a które nie. W przypadku tajemniczego pakietu, który wygląda na to, że nigdzie nie jest używany, cofnij się i sprawdź, które zależności najwyższego poziomu mogą go potrzebować. Spróbuj je oddzielić.
Sytuacja jest nieco bardziej skomplikowana, jeśli chodzi o usuwanie niepotrzebnych bibliotek. Ważne jest, aby ściśle współpracować z zespołem, i sprawdzić, czy istnieje możliwość uproszczenia części kodu. Usunięcie języka moment
w tej aplikacji może wydawać się właściwe za każdym razem, ale co, jeśli trzeba obsługiwać strefy czasowe i różne języki? A co, jeśli dochodzi do bardziej złożonych manipulacji datami? Manipulacja datami i godzinami oraz ich analizowanie może stać się bardzo trudne, a biblioteki takie jak moment
i date-fns
znacznie to upraszczają.
Wszystko się kompromisuje i trzeba ocenić, czy warto złożoność i wysiłek, aby wdrożyć niestandardowe rozwiązanie, zamiast polegać na bibliotece zewnętrznej.