Ogranicz ładunki JavaScript dzięki podziałowi kodu

Większość stron internetowych i aplikacji składa się z wielu różnych części. Zamiast wysyłać cały kod JavaScript, który tworzy aplikację, zaraz po załadowaniu pierwszej strony, podziel go na kilka fragmentów, aby zwiększyć wydajność strony.

W tym ćwiczeniu pokazujemy, jak używać dzielenia kodu, aby zwiększyć wydajność prostej aplikacji, która sortuje 3 liczby.

W oknie przeglądarki widać aplikację o nazwie Magic Sorter z 3 polami do wpisywania liczb i przyciskiem sortowania.

Zmierz odległość

Jak zawsze, przed próbą dodania jakichkolwiek optymalizacji ważne jest, aby najpierw zmierzyć wydajność witryny.

  1. Aby wyświetlić podgląd witryny, naciśnij Wyświetl aplikację, a następnie Pełny ekran pełny ekran.
  2. Naciśnij `Control+Shift+J` (lub `Command+Option+J` na Macu), aby otworzyć Narzędzia deweloperskie.
  3. Kliknij kartę Sieć.
  4. Zaznacz pole wyboru Wyłącz pamięć podręczną.
  5. Ponownie uruchom aplikację.

Panel Sieć pokazujący pakiet JavaScript o rozmiarze 71,2 KB.

71,2 KB kodu JavaScript tylko po to, aby posortować kilka liczb w prostej aplikacji. Dlaczego?

W kodzie źródłowym (src/index.js) biblioteka lodash jest importowana i używana w tej aplikacji. Lodash udostępnia wiele przydatnych funkcji użytkowych, ale w tym przypadku używana jest tylko jedna metoda z pakietu. Częstym błędem jest instalowanie i importowanie całych zależności od innych firm, gdy wykorzystywana jest tylko ich niewielka część.

Optymalizuj

Rozmiar pakietu można zmniejszyć na kilka sposobów:

  1. Napisz niestandardową metodę sortowania zamiast importować bibliotekę innej firmy
  2. Użyj wbudowanej metody Array.prototype.sort(), aby posortować liczbowo
  3. Zaimportuj tylko metodę sortBy z lodash, a nie całą bibliotekę
  4. Pobierz kod sortowania tylko wtedy, gdy użytkownik kliknie przycisk

Opcje 1 i 2 to doskonałe metody zmniejszania rozmiaru pakietu (i prawdopodobnie byłyby najbardziej odpowiednie w przypadku prawdziwej aplikacji). Nie używamy ich jednak w tym samouczku, aby nie utrudniać nauki 😈.

Zarówno opcja 3, jak i 4 pomagają zwiększyć wydajność tej aplikacji. W kolejnych sekcjach tego ćwiczenia omówimy te kroki. Podobnie jak w przypadku każdego samouczka dotyczącego kodowania, zawsze staraj się pisać kod samodzielnie, zamiast go kopiować i wklejać.

Importuj tylko to, czego potrzebujesz

Musisz zmodyfikować kilka plików, aby zaimportować tylko jedną metodę z lodash. Na początek zastąp tę zależność w pliku package.json:

"lodash": "^4.7.0",

w ten sposób:

"lodash.sortby": "^4.7.0",

Teraz w pliku src/index.js zaimportuj ten konkretny moduł:

import "./style.css";
import _ from "lodash";
import sortBy from "lodash.sortby";

Zaktualizuj sposób sortowania wartości:

form.addEventListener("submit", e => {
  e.preventDefault();
  const values = [input1.valueAsNumber, input2.valueAsNumber, input3.valueAsNumber];
  const sortedValues = _.sortBy(values);
  const sortedValues = sortBy(values);

  results.innerHTML = `
    <h2>
      ${sortedValues}
    </h2>
  `
});

Ponownie załaduj aplikację, otwórz Narzędzia deweloperskie i jeszcze raz spójrz na panel Sieć.

Panel Sieć z pakietem JavaScript o rozmiarze 15,2 KB.

W przypadku tej aplikacji rozmiar pakietu został zmniejszony ponad 4-krotnie przy bardzo niewielkim nakładzie pracy, ale nadal można go jeszcze zmniejszyć.

Podział kodu

webpack to jeden z najpopularniejszych obecnie używanych modułów pakujących typu open source. Krótko mówiąc, łączy wszystkie moduły JavaScript (oraz inne zasoby), które składają się na aplikację internetową, w pliki statyczne, które mogą być odczytywane przez przeglądarkę.

Pojedynczy pakiet używany w tej aplikacji można podzielić na 2 osobne fragmenty:

  • Jedna odpowiada za kod, który tworzy naszą początkową trasę,
  • Dodatkowy fragment zawierający kod sortowania.

Dzięki importom dynamicznym fragment dodatkowy może być ładowany leniwie lub na żądanie. W tej aplikacji kod, który tworzy fragment, może zostać wczytany tylko wtedy, gdy użytkownik naciśnie przycisk.

Zacznij od usunięcia importu najwyższego poziomu dla metody sortowania w pliku src/index.js:

import sortBy from "lodash.sortby";

Zaimportuj go w detektorze zdarzeń, który jest uruchamiany po naciśnięciu przycisku:

form.addEventListener("submit", e => {
  e.preventDefault();
  import('lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

Funkcja import() jest częścią propozycji (obecnie na etapie 3 procesu TC39) dotyczącej możliwości dynamicznego importowania modułu. Webpack obsługuje już tę funkcję i stosuje tę samą składnię, która została opisana w propozycji.

import() zwraca obietnicę, a gdy zostanie ona spełniona, udostępniany jest wybrany moduł, który jest podzielony na osobne fragmenty. Po zwróceniu modułu module.default jest używany do odwoływania się do domyślnego eksportu dostarczanego przez lodash. Obiekt Promise jest połączony z innym obiektem .then, który wywołuje metodę sortInput, aby posortować 3 wartości wejściowe. Na końcu łańcucha obietniccatch() służy do obsługi przypadków, w których obietnica zostaje odrzucona z powodu błędu.

Ostatnią rzeczą, którą należy zrobić, jest zapisanie metody sortInput na końcu pliku. Musi to być funkcja, która zwraca funkcję przyjmującą zaimportowaną metodę z lodash.sortBy. Funkcja zagnieżdżona może następnie posortować 3 wartości wejściowe i zaktualizować DOM.

const sortInput = () => {
  return (sortBy) => {
    const values = [
      input1.valueAsNumber,
      input2.valueAsNumber,
      input3.valueAsNumber
    ];
    const sortedValues = sortBy(values);

    results.innerHTML = `
      <h2>
        ${sortedValues}
      </h2>
    `
  };
}

Monitoruj

Załaduj aplikację po raz ostatni i uważnie obserwuj panel Sieć. Po wczytaniu aplikacji pobierany jest tylko niewielki pakiet początkowy.

Panel Sieć z pakietem JavaScript o rozmiarze 2,7 KB.

Po naciśnięciu przycisku w celu posortowania wprowadzonych liczb fragment zawierający kod sortowania jest pobierany i wykonywany.

Panel Sieć, w którym widać pakiet JavaScript o rozmiarze 2,7 KB, a następnie pakiet JavaScript o rozmiarze 13,9 KB.

Zwróć uwagę, że liczby nadal są sortowane.

Podsumowanie

Dzielenie kodu i leniwe ładowanie mogą być niezwykle przydatnymi technikami zmniejszania początkowego rozmiaru pakietu aplikacji, co może bezpośrednio przełożyć się na znacznie krótszy czas wczytywania strony. Zanim jednak zastosujesz tę optymalizację w aplikacji, musisz wziąć pod uwagę kilka ważnych kwestii.

Interfejs leniwego ładowania

Podczas leniwego ładowania określonych modułów kodu należy wziąć pod uwagę, jak będzie wyglądać korzystanie z aplikacji przez użytkowników ze słabszymi połączeniami sieciowymi. Podzielenie i wczytanie bardzo dużego fragmentu kodu, gdy użytkownik przesyła działanie, może sprawić, że aplikacja będzie wyglądać, jakby przestała działać, dlatego warto wyświetlić jakiś wskaźnik wczytywania.

Leniwe ładowanie modułów węzłów innych firm

Leniwe ładowanie zależności od innych firm w aplikacji nie zawsze jest najlepszym rozwiązaniem. Zależy to od tego, gdzie ich używasz. Zwykle zależności od innych firm są dzielone na osobny pakiet vendor, który można zapisać w pamięci podręcznej, ponieważ nie są one aktualizowane tak często. Więcej informacji o tym, jak może Ci w tym pomóc SplitChunksPlugin, znajdziesz w tym artykule.

Leniwe ładowanie z użyciem platformy JavaScript

Wiele popularnych platform i bibliotek, które używają webpacka, udostępnia abstrakcje ułatwiające leniwe ładowanie w porównaniu z używaniem dynamicznych importów w środku aplikacji.

Chociaż warto wiedzieć, jak działają importy dynamiczne, zawsze używaj metody zalecanej przez platformę lub bibliotekę do leniwego ładowania określonych modułów.

Wstępne ładowanie i pobieranie z wyprzedzeniem

Jeśli to możliwe, korzystaj ze wskazówek przeglądarki, takich jak <link rel="preload"> lub <link rel="prefetch">, aby spróbować załadować krytyczne moduły jeszcze szybciej. Webpack obsługuje obie wskazówki dzięki magicznym komentarzom w instrukcjach importu. Szczegółowo wyjaśniamy to w przewodniku Wstępne wczytywanie fragmentów krytycznych.

Leniwe ładowanie nie tylko kodu

Obrazy mogą stanowić znaczną część aplikacji. Leniwe ładowanie elementów, które znajdują się w części strony widocznej po przewinięciu lub poza widocznym obszarem urządzenia, może przyspieszyć działanie witryny. Więcej informacji na ten temat znajdziesz w przewodniku po Lazysizes.