Narzędzia i sposoby na przyspieszenie ładowania stron www
Każda sekunda podczas ładowania strony ma ogromne znaczenie i może znacznie wpłynąć na decyzje użytkowników w sieci. Google w swoich raportach z 2016 roku dostarcza nam informacji, że już po 3 sekundach 75% użytkowników traci cierpliwość i wycofuje się z witryny. Jaki jest optymalny czas ładowania strony? Im krótszy, tym lepiej. Dążąc do idealnego scenariusza, powinniśmy zejść poniżej 3 sekund.
Nie jest to łatwym zadaniem, zwłaszcza w przypadku stron mobilnych. Możemy spodziewać się, że jeśli strona internetowa ładuje się wolno, to czas ładowania jej mobilnej wersji będzie jeszcze dłuższy.
W czasach wzrostu popularności ruchu mobilnego musimy przygotować się na to, że większość użytkowników dociera do naszej strony właśnie z urządzeń mobilnych. Jednak pomimo ciągłego rozwoju technologii, możliwości tych urządzeń są wciąż mniejsze w porównaniu do komputerów desktopowych. Dodatkowym wyzwaniem jest również to, że przeciętni użytkownicy nie posiadają najlepszej jakości smartfonów.
A więc, co zrobić, żeby wyjść naprzeciw ich wymaganiom? W celu stworzenia superszybkiej strony mobilnej najlepiej jest szczegółowo zaplanować jej ,,performance”, czyli efektywność. Świetnych artykułów o tym, co wpływa na szybkość ładowania stron na różnych blogach, są setki. Myślę, że wszyscy słyszeliśmy takie utarte hasła jak redukcja ilości dodatkowych bibliotek, zmniejszenie wielkości i ilości assetów, redukcja ilości requestów, czy poprawa jakości kodu. Dlatego chciałbym omówić ten temat pod kątem całkiem nowego trendu, jakim jest ,,Performance Budget”.
Pracując w Software House, zespoły front-endu zmagają się z tego typu problemami na co dzień. Podzielę się więc kilkoma wskazówkami z perspektywy Front-end Developera, który wciąż poszukuje nowych rozwiązań. W Liki Mobile Solutions, zanim osiągniemy pożądany efekt, dbamy o każdy detal podczas procesu optymalizacji strony, starając się przy tym wdrażać innowacyjne rozwiązania. Wiadomo, że decyzje podjęte na początku realizacji projektu są tymi najbardziej kluczowymi. Dlatego zdecydowałem się przeanalizować, jaki wpływ ma ustalenie i przestrzeganie zasad performance budget na poprawienie szybkości ładowania strony.
Narzędzia
Co zrobić, żeby polepszyć jakość front-endu? Warto zacząć od analizy i przetestowania witryny. Obecnie mamy duży wybór narzędzi, które nam ten krok ułatwią. Większość z nich jest bardzo intuicyjna i sprowadza się do wprowadzenia adresu URL po wejściu w odpowiednią zakładkę.
Google Analytics
To pierwsze narzędzie, do którego warto zajrzeć przy wstępnej analizie. Generuje raporty, dzięki którym wiemy, jak długo zajmuje użytkownikom zobaczenie zawartości naszej strony, w jaki sposób przebiega interakcja z kontentem na stronie oraz w jakich punktach użytkownicy wycofują się z niej.
PageSpeedInsights
Za jego pomocą możemy łatwo zweryfikować prędkość strony. Narzędzie od Google oferuje nam tzw. PageSpeedScore, czyli wynik, jaki może osiągnąć w teście nasza strona w skali od 0 do 100. Najlepiej jest, gdy nasza strona uzyska powyżej 85 punktów. Oczywiście, im wyższy wynik, tym lepiej. Narzędzie podpowiada nam również, co poprawić i w jaki sposób zoptymalizować stronę.
Lighthouse
Jest idealnym rozwiązaniem do zmierzenia web performance, zwłaszcza dla tych, którzy na co dzień używają przeglądarki Chrome. Żeby zacząć korzystać z Lighthouse, trzeba uruchomić narzędzia deweloperskie Chrome’a, a następnie wejść do zakładki Audits oraz kliknąć Perform the Audits. Następnie możemy już przejść do analizy witryny pod kątem: user experience, wydajności czy dobrych praktyk web developmentu.
Redukcja wpływu JavaScriptu na czas ładowania
Wpływ na szybkość ładowania stron internetowych ma nie tylko ilość bajtów przesyłanych do przeglądarki. Mając gotowe pliki, następuje parsowanie, interpretowanie oraz uruchamianie skryptów. Im dłużej to trwa, tym dłużej użytkownik będzie czekać na swoją pierwszą interakcję z naszą aplikacją. Jak widzimy na poniższym screenie z DevToolsów, wykonywanie JavaScriptu (żółty wycinek) zajmuje ⅓ czasu, jaki przeglądarka spędza na renderowaniu strony.
Trzeba przyznać, że jest to dosyć uciążliwe, zwłaszcza gdy korzystamy z gorszej jakości urządzenia. Na szczęście jest kilka rozwiązań, które pozwolą zredukować ten czas do minimum. Oto one:
- Używaj mniej JavaScriptu ;)
- SSR - Server Side Rendering
Używając nowoczesnych frameworków warto pre-renderować aplikacje po stronie serwera. Dzięki SSR czas do First Meaningful Paint będzie krótszy, nie mówiąc już o innych benefitach tego rowiązania jak SEO, Social Media support etc. Będzie to miało duże znaczenie dla użytkowników z gorszym dostępem do internetu albo urządzeń starszej generacji. - Użyj defer do ładowania JSa
<script defer src="https://example.com/script.js"></script>
Gdy przeglądarka widzi atrybut defer, nie przestanie ładować drzewa DOM. Wszystkie te skrypty ładują się od razu, kiedy DOM i CSSOM są ukończone. - Wyłącz nieużywane komponenty bibliotek JSowych
Czasami większe biblioteki pozwalają wybrać sekcje, które będziemy używać do rozwoju naszej aplikacji - Przenieś długo trwające zadania JSowe do Web Workerów
- Unikaj setTimeout lub setInterval do przeprowadzania zmian w wyglądzie strony
- Minifikuj kod
- Używaj narzędzi typu Lighthouse
Audyt zawsze zawiera garść informacji, które pomogą znaleźć słabe strony naszej aplikacji. - Śledź słabe strony aplikacji
W celu zrobienia tego na faktycznych urządzeniach swoich użytkowników możesz użyć całkiem nowego rozwiązania, jakim jest PerformanceObserver oraz wspomnianego już wyżej Google Analytics do wizualizacji danych.
Dla przykładu:
Śledzenie długich tasków
Zadania, które trwają dłuższy czas, mogą zniechęcić użytkownika do korzystania z naszej aplikacji. By je znaleźć i zmierzyć, możemy użyć poniższego kawałka kodu:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
ga('send', 'event', {
eventCategory: 'Performance Metrics',
eventAction: 'longtask',
eventValue: Math.round(entry.startTime + entry.duration),
eventLabel: JSON.stringify(entry.attribution),
});
}
});
observer.observe({entryTypes: ['longtask']});
Śledzenie zbyt długich reakcji na przyciskach
Dokładnie jak w punkcie poprzednim. Odpowiedź na kliknięcie przycisku nie powinna być dłuższa niż 100 ms. Jeżeli mamy podejrzenie, że zajmuje więcej czasu, możemy upewnić się, używając poniższego kawałka kodu:
subscribeBtn.addEventListener('click', event => {
// tutaj handler przycisku
const lag = performance.now() - event.timeStamp;
if (lag > minVal (na przykład 100)) {
ga('send', 'event', {
eventCategory: 'Performance Metric'
eventAction: 'input-latency',
eventLabel: '#subscribe:click',
eventValue: lag,
nonInteraction: true,
});
}
});
Śledzenie First Paint (FP)
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
const metricName = entry.name;
const time = Math.round(entry.startTime + entry.duration);
ga('send', 'event', {
eventCategory: 'Performance Metrics',
eventAction: metricName,
eventValue: time,
nonInteraction: true,
});
}
});
observer.observe({entryTypes: ['paint']});
10. Dobierz wersję builda do przeglądarki usera:
Pozwala nam to ustawić listę przeglądarek, dla której babel tworzy dwa pliki bundle. Jeden kompilowany jest do JS, rozumianego przez wszystkie przeglądarki, a drugi dla wspierających ES6+. Możemy je rozróżnić i załadować, odpowiednio używając atrybutu type=”module”
i nomodule
.
Dzięki temu podejściu możemy zredukować wielkość pliku niemal o połowę, a działać to będzie już dla większości nowoczesnych przeglądarek.
- wersja “nomodule”
- wersja niekompilowana
Performance Budget
Zdecydowanie powinniśmy zapoznać się z tym terminem, jeśli chcemy zaplanować strategię zmniejszenia wagi strony. Pomoże to nam uniknąć wolnego ładowania strony oraz słabego performance.
Chcę, żeby moja strona była szybka. W ten sposób nietechniczna osoba, podejmująca decyzje dotyczące projektu, może sformułować cel dotyczący optymalizacji strony. Performance budget pomoże nam lepiej sprecyzować cele do zrealizowania. Tak może przedstawiać się nasz przykładowy budżet.
- Nasza strona ma ważyć mniej niż 1MB
- Nasza strona główna musi ładować maksymalnie 150KB na telefonach
- Nasza strona musi zawierać mniej niż 4 MB zdjęć na desktopie, a 2MB na telefonie
- Nasza strona musi się załadować i umożliwić interakcje w mniej niż 5 sekund na wolnym 3G
- Lighthouse scoremusi być powyżej 85 punktów.
Główną ideą performance budget jest założenie minimalnych kryteriów dla np:
- czasu ładowania strony dla 3G/4G etc,
- maksymalnej wielkość pliku JS-owego
- maksymalnej wielkość obrazków
- punktów z Lighthouse lub innych narzędzi, których zespół nie może przekroczyć.
- czasu na pierwszą interakcję użytkownika
- oraz wszystkich innych liczb, które dzięki zastosowaniu performance budget możemy łatwo zmierzyć.
Każdy kawałek kodu, który w nieuzasadniony sposób przekracza jedno z kryteriów, powinien być odrzucany w procesie PR review. Dla przyspieszenia procesu mergowania, mamy zestaw narzędzi, które możemy łatwo zintegrować z naszym repozytorium, a nawet zablokować tworzenie pull requestów.
Warto wspomnieć, że zdefiniowanie i opisanie takich zasięgów powinno być przygotowane na samym początku projektu, w czasie opisu minimalnych wymagań. Jest to idealny sposób komunikacji z naszym biznesem i designeremi. Dla nich to informacja, żeby nie przeciążać strony filmami HD, karuzelą zdjęć czy przesadną ilością fontów.
Narzędzia pomagające śledzić kryteria
Webpack w wersji 2.2RC +
Wprowadza wsparcie dla performance budget. A mianowicie ostrzega nas, gdy JS bundle przekroczy jakąś wielkość. Jeżeli chciałbyś to dostosować do swojego projektu, spróbuj ustawić to tak:
performance: {
maxAssetSize: 100000,
maxEntrypointSize: 300000,
hints: 'warning'
},
Co więcej, wprowadzono również wsparcie dla code splittingu i prawidłowych wzorców ładowania contentu.
Speed Curve
Dostarcza informację zwrotną na temat wpływu kodu na wydajność strony. Pozwala śledzić ,,performance” strony oraz mówi nam, jak strona wypada na tle konkurencji. W Speed Curve można również otrzymywać alerty na temat performance budget. Jest to świetne narzędzie do sprawdzenia wydajności naszej strony, ponieważ odnosi się do danych biznesowych. Pozwoli nam zmierzyć współczynnik odrzuceń strony, a tym samym zrozumieć lepiej doświadczenie jej odbiorców. Przy ustalaniu budżetu mamy do dyspozycji szeroki zakres wskaźników, które możemy odnieść do kategorii z Lighthouse.
Tego typu alerty informują np. o przekroczeniu ustalonego budżetu dla JavaScript.
Performancebudget.io
Jest to narzędzie przydatne szczególnie wtedy, gdy jesteśmy na pierwszym etapie planowania budżetu wydajności strony. Pomoże nam skalkulować oraz zwizualizować budżet, uwzględniając różne czasy ładowania strony.
Dostosować się do budżetu czy dostosować budżet?
Dodając nową funkcjonalność lub zmieniając wymagania, nie będzie dla nikogo zaskoczeniem, że może to wpłynąć na budżet. Niestety, nie zawsze wszystkie wymagania pozwolą nam na rozwój aplikacji bez zmian w budżecie. Natomiast gdy dojdzie do takiej sytuacji, jest zawsze kilka ruchów, które możemy wykonać:
- Optymalizacja kodu. Może to jest właśnie ten czas, gdy powinniśmy się pochylić nad możliwościami poprawienia jakości swojego kodu lub przejścia przez listę TODO, którą załączam na końcu :)
- Musimy sobie odpowiedzieć na pytanie, czy ta nowa funkcjonalność jest warta zmian w budżecie, który z kolei wpłynie na performance i szybkość ładowania strony.
- Rezygnacja z innych, teoretycznie ciężkich funkcjonalności, na rzecz nowej. Czasami nie musi być to kompletna rezygnacja. Może to być wyłączenie z jakiejś podstrony, na której nie potrzebujemy danej funkcjonalności, ładowania danego kawałka kodu.
- Dostosowanie budżetu do nowych zmian.
Podsumowanie
Dobrze wykonany i zarządzany performance budget to potężne narzędzie w procesie PR review. Pozwoli nam to pilnować wszystkich najważniejszych zagadnień związanych z performance od samego początku procesu wytwarzania oprogramowania. Od kiedy w LikiMS wdrożyliśmy ten system, zaoszczędziliśmy bardzo dużo czasu na ewentualnych poprawkach w procesie QA. Kod jest czysty, wydajny, aplikacje ładują się szybko i są responsywne na działania użytkownika. Polecam samodzielne wypróbowanie tej metodyki.
Checklista
Assets
- Upewnij się, że każde zdjęcie ma odpowiedni format. Typowym błędem jest używanie nieprawidłowych formatów np. PNG zamiast JPEG. To właśnie JPEG będzie zazwyczaj prawidłowym formatem dla dużych obrazów np. tła, a zarazem pozwoli znacznie zmniejszyć czas ładowania strony. Użycie WebP będzie w takim wypadku nawet lepszym rozwiązaniem, ale powinniśmy wtedy zapewnić fallback do powszechnie wspieranego JPEG.
- Optymalizacja zdjęć, np. poprzez kompresję. Możemy użyć do tego aplikacji typu tinyjpg lub compressor.
- Używaj wektorów zamiast gotowych bitmap, kiedy to możliwe. SVG będzie zawsze mniejsze od np PNG.
- Lazy loading dla obrazków poza ekranem.
- Zawsze ustawiaj width i height dla <img> jeżeli znasz finalny rozmiar zdjęcia.
- Dla czcionek staraj się używać formatu WOFF2, który jest około 30% mniejszy, niż WOFF 1.0
- Używaj preload do ładowania fontów.
<link rel="preload" as="font" crossorigin="crossorigin" type="font/woff2" href="myfont.woff2">
HTML
- Ustaw ładowanie CSSów przed ładowaniem JS. Umożliwi to lepsze ładowanie źródeł w tym samym czasie.
- Upewnij się że, Twój kod jest semantyczny. Przeglądarka najpierw przeprowadza testy dla poprawności HTMLa.
- Minifikuj HTML usuwając komentarze, białe znaki i nowe linie.
- Usuń niepotrzebne atrybuty. Wiele z nich nie jest już wymaganych w HTML5.
- Używaj async i defer kiedy to możliwe.
CSS
- Minifikuj CSS
- Połącz core styli w jeden plik oraz wczytaj komponenty potrzebne tylko dla danej podstrony.
- Usuń nieużywane CSS selectory. Często w czasie refaktorowania kodu zapominamy usuwać niepotrzebny już kod.
JavaScript
- Minifikuj JS.
- Ładuj pliki JS asynchronicznie, używając async i defer.
- Aktualizuj biblioteki do najnowszych wersji.
- Mądrze wybieraj biblioteki do swojego projektu. Może lepiej znaleźć znacznie mniejsze rozwiązania, ale skrojone pod nasze potrzeby? Może jest biblioteka, której nie trzeba importować w całości a tylko interesujące nas części (polecam plugin do VSC).
- Upewnij się, że korzystając, np. z webpacka masz uruchomiony tree shaking.
- Używaj code-splitting, by wczytywać tylko kod potrzebny dla danej ścieżki.
- Zoptymalizuj wszystkie swoje algorytmy.
- Usuń nieużywany kod.