Tworzymy witryny w większym stopniu bazujące na języku JavaScript, więc czasem płacimy za to, co przesyłamy w sposób, który nie zawsze jest łatwo widoczny. Z tego artykułu dowiesz się, dlaczego warto odrobić dyscyplinę, jeśli chcesz, by Twoja witryna się ładowała i działała szybko na urządzeniach mobilnych. Im mniej kodu JavaScript, tym mniej czasu poświęcanego na transmisję danych w sieci, mniej czasu poświęcanego na dekompresję kodu oraz mniej czasu na analizowanie i kompilowanie tego kodu.
Sieć
Większość programistów bierze pod uwagę koszty JavaScriptu w świetle kosztów pobierania i wykonywania. Wysyłanie większej liczby bajtów JavaScriptu przez kabel trwa dłużej, im wolniejsze jest połączenie.
Może to być problem, ponieważ efektywny typ połączenia sieciowego użytkownika może nie być 3G, 4G ani Wi-Fi. Możesz korzystać z kawiarni przez Wi-Fi, ale możesz też połączyć się z komórkowym hotspotem o szybkości 2G.
Możesz obniżyć koszt przesyłania danych w sieci JavaScriptu poprzez:
- Wysyłanie tylko kodu potrzebnego użytkownikowi.
- Użyj podziału kodu, aby podzielić JavaScript na elementy o znaczeniu krytycznym, a które nie. Moduły do tworzenia pakietów, takie jak webpack, obsługują dzielenie kodu.
- Leniwe ładowanie w kodzie, który nie jest krytyczny.
- Minifikacja
- Do zmniejszenia kodu ES5 użyj UglifyJS.
- Aby zmniejszyć ES2015+, użyj narzędzia babel-minify lub uglify-es.
- Kompresja
- Usuwanie nieużywanego kodu
- Identyfikuj możliwości tworzenia kodu, który można usunąć lub leniwie ładować, korzystając z pokrycia kodu z Narzędzi deweloperskich.
- Aby uniknąć transpilacji funkcji, które są już obecne w nowoczesnych przeglądarkach, użyj atrybutów babel-preset-env i listy przeglądarki. Zaawansowani programiści mogą zauważyć, że uważna analiza pakietów pakietów internetowych pomaga zidentyfikować możliwości zmniejszenia niepotrzebnych zależności.
- Aby dowiedzieć się, jak usunąć kod, przeczytaj o potrząsaniu drzewem, o zaawansowanych optymalizacji i wtyczce przycinania w bibliotece Closure Compiler, np. lodash-babel-plugin lub ContextReplacementPlugin pakietu bibliotek takich jak Moment.js.
- Buforowanie kodu w celu zminimalizowania ruchu sieciowego.
- Używaj buforowania HTTP, aby zapewnić skuteczne odpowiedzi przeglądarki w pamięci podręcznej. Aby uniknąć przenoszenia niezmienionych bajtów, ustal optymalny czas trwania skryptów (max-age) i tokeny weryfikacyjne (ETag).
- Buforowanie skryptu service worker może zwiększyć stabilność sieci aplikacji i zapewnić Ci łatwy dostęp do funkcji takich jak pamięć podręczna kodu V8.
- Używaj długoterminowego buforowania, aby uniknąć konieczności ponownego pobierania zasobów, które się nie zmieniły. Jeśli korzystasz z pakietu Webpack, zapoznaj się z informacjami na temat szyfrowania nazw plików.
Analiza/kompilacja
Jednym z największych kosztów JavaScriptu po pobraniu jest jego analiza/skompilowanie. W Narzędziach deweloperskich w Chrome analiza i kompilacja wchodzą w skład żółtego czasu „Obsługa skryptów” w panelu wydajności.
Karty Dół Up i Drzewo połączeń pokazują dokładne czasy analizy/kompilacji:
![ALT_TEXT_HERE](https://web.developers.google.cn/static/articles/optimizing-content-efficiency-javascript-startup-optimization/image/alttexthere-cfd35a90562dd.png?authuser=7&hl=pl)
Dlaczego jednak to takie ważne?
Jeśli poświęcisz dużo czasu na analizowanie lub kompilowanie kodu, może to znacznie opóźnić czas, przez jaki użytkownik będzie mógł wejść w interakcję z Twoją witryną. Im więcej kodu JavaScript wyślesz, tym dłużej potrwa jego przeanalizowanie i skompilowanie, zanim witryna stanie się interaktywna.
Bajt na bajt – obsługa języka JavaScript jest droższa w przeglądarce niż odpowiedni rozmiar obrazu lub czcionki internetowej – Tom Dale
W porównaniu z JavaScriptem przetwarzanie obrazów o równej wielkości wiąże się z dużymi kosztami (konieczne jest ich zdekodowanie), jednak przeciętnie w przypadku sprzętu mobilnego JS może mieć negatywny wpływ na interaktywność strony.
![ALT_TEXT_HERE](https://web.developers.google.cn/static/articles/optimizing-content-efficiency-javascript-startup-optimization/image/alttexthere-e3dc86ddc7603.png?authuser=7&hl=pl)
Gdy mówimy o powolnym analizowaniu i kompilowaniu danych, ważny jest kontekst – rozmawiamy tu o przeciętnych telefonach komórkowych. Przeciętny użytkownik ma telefony z wolnym procesorem i układem GPU, bez pamięci podręcznej L2/L3, a nawet z ograniczoną pamięcią.
Możliwości sieciowe i możliwości urządzeń nie zawsze są zgodne. Użytkownik ze świetnym połączeniem światłowodowym nie musi mieć najlepszego procesora do przeanalizowania i oceny kodu JavaScript wysłanego na jego urządzenie. To samo dzieje się również przy kiepskim połączeniu sieciowym, ale o niesamowicie szybkim procesorze. – KristoferBaxter, LinkedIn
Poniżej możesz zobaczyć koszt analizy ok. 1 MB zdekompresowanego (prostego) JavaScriptu na słabszych i zaawansowanych sprzęcie. Najszybsze telefony na rynku i przeciętne telefony o nazwie 2–5 razy różnią się od siebie o 2–5 razy różnicy w czasie.
![ALT_TEXT_HERE](https://web.developers.google.cn/static/articles/optimizing-content-efficiency-javascript-startup-optimization/image/alttexthere-52af247f207f5.png?authuser=7&hl=pl)
A co z prawdziwymi stronami, np. CNN.com?
W zaawansowanych telefonach iPhone 8 przetworzenie lub skompilowanie kodu JS CNN zajmuje zaledwie 4 s, a w przypadku przeciętnego telefonu (Moto G4) trwa to ok. 13 s. Może to znacząco wpłynąć na to, jak szybko użytkownik będzie mógł w pełni korzystać z tej witryny.
![ALT_TEXT_HERE](https://web.developers.google.cn/static/articles/optimizing-content-efficiency-javascript-startup-optimization/image/alttexthere-7cafa788a7bdf.png?authuser=7&hl=pl)
To pokazuje, jak ważne jest testowanie przeciętnego sprzętu (np. Moto G4), a nie tylko telefonu, który możesz mieć w kieszeni. Kontekst ma jednak znaczenie: optymalizuj użytkowników pod kątem stanu urządzenia i sieci.
![ALT_TEXT_HERE](https://web.developers.google.cn/static/articles/optimizing-content-efficiency-javascript-startup-optimization/image/alttexthere-6de3a79335e9b.png?authuser=7&hl=pl)
Czy naprawdę wysyłamy zbyt dużo kodu JavaScript? Eee, być może :)
Korzystając z archiwum HTTP (około 500 tys. pierwszych witryn) do analizy stanu JavaScriptu na urządzeniach mobilnych, widzimy, że 50% witryn wymaga 14-sekundowej interaktywności. Takie witryny potrzebują do 4 sekund na analizowanie i kompilowanie kodu JS.
Weź pod uwagę czas potrzebny na pobieranie i przetwarzanie kodu JS oraz innych zasobów. Nic dziwnego, że użytkownicy mogą poczekać, aż strony będą gotowe do użycia. Tutaj z pewnością sobie poradzimy.
Usunięcie niekrytycznego kodu JavaScript ze stron może skrócić czas transmisji oraz intensywnie przetwarzać procesor i skompilować kod JavaScript, a także zmniejszyć ilość pamięci. Przyspiesza to też interakcję między stronami.
Czas wykonywania
Nie tylko analizowanie i kompilowanie wiąże się z kosztami. Wykonanie JavaScriptu (po przeanalizowaniu/skompilowaniu kodu) to jedna z operacji, które muszą zostać wykonane w wątku głównym. Długi czas wykonywania kodu może też wpłynąć na to, jak szybko użytkownik będzie mógł wejść w interakcję z witryną.
Jeśli skrypt jest wykonywany przez ponad 50 ms, czas do pełnej interaktywności jest opóźniony o całkowity czas potrzebny na pobranie, skompilowanie i wykonanie kodu JS – Alex Russell.
Aby rozwiązać ten problem, JavaScript powinien być tworzony w małych fragmentach, co pozwala uniknąć zablokowania głównego wątku. Sprawdź, czy możesz zmniejszyć ilość pracy wykonywanej podczas wykonywania zadania.
Inne koszty
JavaScript może wpływać na wydajność strony w inny sposób:
- Pamięć. Strony mogą się często zawieszać lub zacinać się z powodu czyszczenia pamięci (GC). Gdy przeglądarka odzyska pamięć, wykonanie kodu JS jest wstrzymywane, aby przeglądarka często zbierająca śmieci mogła wstrzymywać wykonywanie kodu częściej niż powinna. Unikaj wycieków pamięci i częstych wstrzymywania GC, aby uniknąć zacinania się stron.
- W czasie działania długo działający JavaScript może zablokować wątek główny, powodując, że strony nie odpowiadają. Podzielenie zadania na mniejsze części (za pomocą
requestAnimationFrame()
lubrequestIdleCallback()
do planowania) może zminimalizować problemy z czasem reakcji, co może poprawić interakcje z kolejnym wyrenderowaniem (INP).
Wzorce obniżania kosztów dostarczania JavaScript
Jeśli próbujesz utrzymać powolne czasy analizy/kompilowania i przesyłania danych w sieci w przypadku JavaScriptu, możesz korzystać z wzorców, które ułatwiają dzielenie się fragmentami na podstawie trasy lub PRPL.
Przygotowanie do egzaminów PRPL
PRPL (Push, Render, Pre-cache, Lazy-load) to wzorzec, który optymalizuje pod kątem interaktywności przez agresywny podział kodu i buforowanie w pamięci podręcznej:
Zobaczmy, jaki może to mieć wpływ.
Analizujemy czas wczytywania popularnych stron mobilnych i progresywnych aplikacji internetowych, korzystając ze statystyk wywołań środowiska wykonawczego w V8. Jak widać, analizowanie czasu (zaznaczone na pomarańczowo) stanowi znaczną część czasu spędzanego w wielu witrynach:
Wego, witryna wykorzystująca PRPL, utrzymuje krótki czas analizy tras, dzięki czemu bardzo szybko się uaktywnia. Wiele z powyższych witryn wdrożyło podział kodu i budżety wydajności, aby spróbować obniżyć koszty kodu JavaScript.
Wczytywanie progresywne
Wiele witryn optymalizuje widoczność treści kosztem interakcji. Aby uzyskać szybkie pierwsze wyrenderowanie, gdy masz duże pakiety JavaScriptu, programiści stosują czasem renderowanie po stronie serwera, a następnie „uaktualnianie” go w celu dołączenia modułów obsługi zdarzeń po ostatecznym pobraniu kodu JavaScript.
Zachowaj ostrożność, ponieważ wiąże się to z własnymi kosztami. 1) Na ogół wysyłasz większą odpowiedź HTML, która może zwiększyć naszą interaktywność, 2) może pozostawić użytkownika w niesamowitej dolinie, w której połowa reklamy nie będzie interaktywna do czasu zakończenia przetwarzania JavaScriptu.
Lepszym rozwiązaniem może być progresywne wczytywanie. Wyślij w dół stronę o minimalistycznym działaniu (składaną wyłącznie z kodu HTML/JS/CSS niezbędnych dla bieżącej trasy). W miarę pojawiania się kolejnych zasobów aplikacja będzie mogła leniwie ładować się i odblokowywać kolejne funkcje.
![ALT_TEXT_HERE](https://web.developers.google.cn/static/articles/optimizing-content-efficiency-javascript-startup-optimization/image/alttexthere-bc9d1b36573cd.png?authuser=7&hl=pl)
Wczytywanie kodu proporcjonalne do tego, co widać, to święty Graal. W tym celu mogą pomóc PRPL i progresywne wczytywanie.
Podsumowanie
Rozmiar transmisji ma kluczowe znaczenie w sieciach niskiej jakości. Czas analizy jest ważny w przypadku urządzeń powiązanych z CPU. Utrzymywanie tych niskich wartości jest istotne.
Zespoły z powodzeniem stosują wysokie budżety wydajności, aby utrzymać krótki czas przesyłania oraz analizowania i kompilacji JavaScriptu. Zobacz film Alexa Russella „Can You Afford It?: Rzeczywista skuteczność w internecie Budżety” w celu uzyskania wskazówek dotyczących budżetów na reklamy mobilne.
![ALT_TEXT_HERE](https://web.developers.google.cn/static/articles/optimizing-content-efficiency-javascript-startup-optimization/image/alttexthere-72d5f9f9722e.png?authuser=7&hl=pl)
Jeśli tworzysz witrynę na urządzenia mobilne, postaw na reprezentatywny sprzęt, skróć czas analizy i kompilacji JavaScriptu oraz zastosuj budżet wydajności, który pozwoli Twojemu zespołowi monitorować koszty JavaScriptu.
Więcej informacji
- Chrome Dev Summit 2017 – sprawdzone metody dotyczące nowoczesnego wczytywania
- Skuteczność uruchamiania z JavaScriptem
- Jak radzić sobie z kryzysem wydajności w internecie – Nolan Lawson
- Czy stać Cię na to? Rzeczywiste budżety na skuteczność — Alex Russell
- Ocena bibliotek i platform internetowych – Kristofer Baxter
- Wyniki eksperymentów Cloudflare pod kątem kompresji (uwaga: dynamiczny Brotli o wyższej jakości może opóźnić pierwsze renderowanie strony, dlatego uważnie dokonaj oceny). lepiej statycznie skompresowany).
- Transakcje terminowe wydajności – Sam Saccone