Jak zadbać o wydajność frontendu. Devdebata

Wracamy z kolejnym tematem, który trudno rozstrzygnąć w postaci artykułu eksperckiego. Dlatego opracowaliśmy dobrze Wam znany format devdebaty po to, by poznać opinie różnych frontend developerów na te same kwestie. Zobaczcie, co zaproszeni seniorzy myślę o wydajności we frontendzie.

Odpowiedzi na pytania udzielili:

Andrii Los. Senior Frontend Engineer w Revolut. Got 6 years of experience in Software Engineering in BigData related projects and typical Java Web projects using Spring Framework. Previously was Java Backend Engineer, most recent and strong tech expertises are related to TypeScript, React, GraphQL, CSS-in-JS.

Artem Shtepenko. Senior Frontend Engineer w Revolut. I have begun programming when I was 16 years old from simple web pages, next I studied Computer Science at University of Marii Curie-Skłodowskiej in Lublin. After that I worked as Full Stack Developer at Asseco Business Solutions, now I am working at Revolut.

Adam Bar. Full-stack developer w Bright Inventions, gdańskim software housie specjalizującym się w rozwiązaniach mobilnych, IoT oraz Blockchainie. Doświadczony w kilku stosach technologicznych, ostatnio wierny TypeScriptowi. Pasjonat Mobile Weba, twórca What Web Can Do Today, strony o możliwościach Weba na urządzeniach mobilnych.

1. Temat wydajności na back-endzie jest znany od lat i dla wiele osób to istotna kwestia. Z kolei ten sam temat front-endzie jest często zaniedbywany. W jaki sposób możemy zadbać o performance front-endu?

Odpowiada Andrii Los, Senior Frontend Engineer w Revolut:

Wydajność po stronie frontendu jest niezwykle ważnym zagadnieniem, o które łatwo zadbać stosując proste zasady. Jednocześnie łatwo zaniedbuje się pojęcie wydajności, jeśli programista nie jest świadomy tego, co robi np. nie zna się wspomnianych zasad lub gdy zaimplementuje się zbyt wiele zewnętrznych paczek kodu, nie wiedząc co rzeczywiście jest w ich środku, co powoduje, że program działa coraz wolniej.

Odpowiada Artem Shtepenko, Senior Frontend Engineer w Revolut:

Dodatkowo, szczególnie ważne jest monitorowanie aplikacji pod kątem problemów z wydajnością. Jeżeli dostrzegasz je w logach, bardzo ważne jest ustalenie przyczyny problemów, znalezienie źródła problemu i jego usunięcie, to samo dotyczy strony backendowej.

Odpowiada Adam Bar, Tech Lead & Software Developer w Bright Inventions:

Faktycznie, front-end ostatnimi laty wyewoluował z prostych “stronek” w pełnoprawne aplikacje i nie zawsze z tym poszła wiedza na temat mechanizmów dotyczących wydajności. O ile wydajność na back-endzie w znacznej mierze opiera się o wybór odpowiednich algorytmów i struktur danych, na froncie jest cały szereg dodatkowych kwestii. 

Przede wszystkim powinniśmy zaznajomić się z komunikacją, którą nasz front-end prowadzi przez sieć. Powinniśmy zadbać o odpowiednie cache-owanie statycznych zasobów, zadbać o ich szybkie serwowanie dzięki użyciu CDN-ów oraz włączyć na serwerze HTTP/2, żeby lepiej zrównoleglać ściąganie. Dzięki Service Workerowi możemy wszystkie pliki zapisać na dysku klienta przy pierwszym otwarciu strony i dzięki temu całkowicie wyeliminować koszt odwołań do sieci. Można ponadto rozważyć techniki typu prefetch, żeby z wyprzedzeniem załadować klientowi pliki, o które zapewne za chwilę zapyta. 

Druga kwestia to kolejność, w jakiej nasza aplikacja żąda zasobów. Trzeba mieć świadomość, że każdy plik CSS w sekcji <head> blokuje renderowanie strony na czas jego ściągania. Dlatego serwowanie CSS-ów od ogromnych bibliotek komponentów, z których używamy jednej lub dwóch kontrolek, jest wydajnościowym strzałem w stopę. Także pliki JavaScript, jeżeli nie oznaczymy ich atrybutem “async”, są bardzo kosztowne – blokują parsowanie HTML-a. Ściąganie kodu, którego bezpośrednio w danym momencie nie potrzebujemy (np. kodu innych widoków naszej aplikacji), również nie ma sensu. Współczesne bundlery, np. webpack, oferuje wbudowane rozwiązania tzw. code splittingu, który powinien stać się standardem, jeżeli faktycznie chcemy być w stanie szybko serwować treść użytkownikom.

Trzeci aspekt to interakcje użytkownika ze stroną, np. efekty przejść i animacje. Koszt animacji różnych właściwości elementów może być diametralnie inny, ze względu na pracę, jaką musi wykonać przeglądarka. Przykładowo, zmiana przezroczystości jest bardzo “tania”, a zmiana szerokości elementu wymaga ponownego przeliczenia układu layoutu. Może to być odczuwalne w szczególności na urządzeniach mobilnych, a one stanowią w tej chwili większość ruchu w internecie. Tych zasad jest sporo – warto je znać już na poziomie projektowania UI i UX aplikacji.

2. W jaki sposób z poprawy wydajności mogą skorzystać użytkownicy? Czy wydajność może mieć przełożenie na biznesowe metryki naszego projektu?

Odpowiada Andrii Los, Senior Frontend Engineer w Revolut:

Z pewnością mogą, ale wszystko zależy od konkretnego przypadku. Podobnie jak w kwestii wydajności, nigdy nie zaczynasz optymalizacji czegoś, co wcześniej nie zostało zmierzone. W niektórych bardzo popularnych platformach, takich jak Amazon, eBay i innych, niezwykle ważne jest, aby oszczędzać nawet jedną milisekundę, ponieważ poprawa obciążenia aplikacji nawet o pół sekundy, ma realny wpływ na badania utrzymania liczby użytkowników i ogólnie na przychody z aplikacji. Chociaż musimy pamiętać o tym, że poprawki o pół sekundy naniesione na potężnym Mac Pro podłączonym do porządnego Wi-Fi, w rzeczywistości na 3-4-letnim smartfonie z 3G przyniosą 6-10 sekund poprawy.

Odpowiada Artem Shtepenko, Senior Frontend Engineer w Revolut:

Wiele osób odwiedza strony internetowe na urządzeniach mobilnych, które często nie są tak wydajne, jak komputer stacjonarny. Czas responsywności jest bardzo ważny, bo gdy użytkownik czeka 10+ sekund na otwarcie aplikacji, prawdopodobnie ją zamknie i przejdzie do innej, która ładuje się szybciej. Ale nawet posiadając bardzo wydajne urządzenie mobilne, należy pamiętać o tym jak szybko i stabilnie działa sama sieć. Możesz napisać kod o największej wydajności w historii, ale nie zadziała on, gdy ktoś wrzuci na stronę zdjęcia wielkości 5MB+ i zniszczy całą optymalizację. Na kwestie tzw. performance należy zawsze patrzeć z kilku perspektyw.

Odpowiada Adam Bar, Tech Lead & Software Developer w Bright Inventions:

Są badania, które wprost wiążą wydajność aplikacji ze współczynnikami konwersji. Mówi się, że sekunda ładowania strony dłużej to o 7% mniej konwersji. Dla aplikacji typu e-commerce można to łatwo przeliczyć na stracone kwoty, ale zasada działa dla wszystkich rodzajów aplikacji. Przede wszystkim trzeba myśleć o użytkownikach mobilnych i pod ich kątem testować wydajność aplikacji. Na wolnej sieci ciężka strona może się im po prostu nie załadować, póki starczy im cierpliwości i po prostu przerwą ładowanie. Użytkownik, który nie jest w stanie wejść na stronę, z pewnością nie będzie zadowolonym i lojalnym nabywcą. Co gorsza, takich użytkowników nie zobaczymy nawet w statystykach.

3. Każda optymalizacja to inwestycja, więc zapewne istnieją granice, kiedy usprawnianie wydajności ma sens. Jakie kryteria decydują o tym, kiedy warto pochylić się nad wydajnością front-endu? Na jakim etapie projektu powinno się zwracać na to uwagę? 

Odpowiada Andrii Los, Senior Frontend Engineer w Revolut:

Jeśli jesteś startupem, myślę, że najważniejszą rzeczą jest dostarczenie MVP (minimum viable product) tak szybko, jak to tylko możliwe, z najlepszym możliwym w danym przypadku kodem. Im mniej napisanego przez zespół kodu, tym mniej potencjalnych błędów i możesz szybciej iterować. Jednocześnie szybka iteracja i poleganie na zbyt wielu podmiotach trzecich może skończyć się bałaganem oraz małą wydajnością produktu – co może zaprzepaścić jego szansę na rynku, ale zależy to od innych czynników, m.in jak szybko działa konkurencja. Niemniej, przestrzeganie podejścia co do szybkiego stworzenia MVP, jest lepsze niż polerowanie kodu od zera, gdy w rezultacie nie ma działającego produktu przez wiele miesięcy.

Odpowiada Artem Shtepenko, Senior Frontend Engineer w Revolut:

Pierwszą rzeczą, o której powinieneś pamiętać: przedwczesna optymalizacja jest źródłem wszelkiego zła (a przynajmniej większości) w programowaniu (Donald Knuth). Jeśli masz prostą stronę, na której wyświetlane są dane statyczne, nie musisz ich optymalizować (w większości przypadków), ale jeśli masz listę, która zapewnia ponad 1000 rekordów, wydajność ma znaczenie. Czasami potrzebujemy jakiejś funkcji JAK NAJSZYBCIEJ, ponieważ MVP jest ważnym elementem projektu, szczególnie jeśli pracujesz dla start-upu.

Myślę, że pierwszą zasadą jest zrezygnowanie z implementacji własnego komponentu/ biblioteki, jeżeli masz możliwość korzystania z gotowych rozwiązań. Nawet jeśli nie pracuję na MVP, wolę zacząć od rozwiązania „pod klucz”, ponieważ można zobaczyć, jakie błędy popełniły inne osoby. Na przykład bierzemy bibliotekę A i używamy jej w projekcie, dajesz ją użytkownikom i zbierasz opinie, a następnie możesz je przeanalizować i zdecydować, czy chcesz zoptymalizować tę część aplikacji, czy nie.

Odpowiada Adam Bar, Tech Lead & Software Developer w Bright Inventions:

Są optymalizacje, które są kosztowne i wymagają zmiany architektury projektu, np. code splitting. Dopóki nie mamy danych, świadczących o tym, że to nasz główny problem, pewnie nie ma biznesowego uzasadnienia w wprowadzaniu rewolucji. Ale jeśli startujemy nowy projekt, nie ma z kolei uzasadnienia, żeby nie zadbać o architekturę sprzyjającą wydajności. Z kolei dla istniejących aplikacji jest szereg optymalizacji, które powinno się dać wprowadzić stosunkowo prosto, np. asynchroniczne załączanie skryptów czy preload dla fontów to w zasadzie “jednolinijkowce”. Nie widzę powodu, żeby nie sięgnąć po te “nisko wiszące owoce”.

4. Performance nieraz może stać w sprzeczności z oczekiwaniami biznesu lub wymogami marketingu. Czy dbałość o wydajność aplikacji wymaga szczególnych zasad współpracy biznesu z zespołem developerskim?

Odpowiada Andrii Los, Senior Frontend Engineer w Revolut:

Nie sądzę, że obowiązują specjalne zasady. Powinien to być ciągły dialog między biznesem, marketerami a deweloperami. Obie strony powinny słuchać się nawzajem, aby osiągnąć sensowny kompromis. Jeśli nie ma takiego dialogu, może się to skończyć bałaganem w kodzie, problemami z wydajnością, błędami lub po prostu bardzo opóźnionymi terminami.

Odpowiada Artem Shtepenko, Senior Frontend Engineer w Revolut:

Jeśli oddasz w ręce użytkownika aplikację, która ma problem z wydajnością i szybkością procesów, możesz stworzyć więcej problemów dla biznesu, niż ich rozwiązać. Jeśli wszystko będzie bardzo powolne, użytkownik może przełączyć się na aplikację konkurencji. Dlatego tak ważne jest wypracowanie odpowiedniego balansu pomiędzy szybkością, a wydajnością produktu.

Odpowiada Adam Bar, Tech Lead & Software Developer w Bright Inventions:

Myślę, że niezbędna jest świadomość, że wszystko ma swój koszt i implikacje. Idealnie, jeżeli mielibyśmy statystyki, które pozwolą nam przeliczyć koszt dodania np. kolejnego JavaScriptu śledzącego użytkownika na kwotę, o którą spadnie nam sprzedaż. W praktyce mało kto ma takie dane, co nie zmienia faktu, że potrzebny jest kompromis. Być może developerzy powinni akceptować takie elementy, ale tylko pod warunkiem, że będą dodane w sposób asynchroniczny, a “biznes” zaakceptuje, że przez to potencjalnie kilku użytkowników skrypt nie “uchwyci”, bo opuszczą stronę przed jego załadowaniem. 

Równie ważna, jak nie ważniejsza, jest współpraca developerów z designerami. Designer powinien mieć świadomość, jak projektować UI i UX, żeby unikać kosztownych animacji czy efektów wizualnych spiętych ze scrollowaniem, które zabijają wydajność na telefonach. Zazwyczaj jedyną szansą na taką świadomość jest właśnie feedback od developerów.

5. Na jakie metryki aplikacji, nad którą pracujesz zwracasz uwagę, a na jakie nie i dlaczego?

Odpowiada Andrii Los, Senior Frontend Engineer w Revolut:

Ponieważ pracuję z wewnętrznymi narzędziami, o których wiemy, że będą używane przez całkiem potężne urządzenia i najnowszy Chrome, z przyzwoitą prędkością Internetu itp. zwracamy uwagę na podstawowe metryki. Mówiąc o naszej stronie internetowej, czy ogólnie, dowolnej aplikacji internetowej, którą zamierzasz przekazać użytkownikowi, bardzo ważne jest, aby metryki były w dobrym stanie: rozmiar pakietu JS jest mniejszy niż 300 KB, paint poniżej 2 sekund dla większości urządzeń, gzip lub innej kompresji zasobów, CDN na całym świecie, polityka buforowania, szybkość działania aplikacji na każdym urządzeniu. I warto zawsze mierzyć metryki przed działaniami nad zwiększeniem wydajności apki. Nigdy nie optymalizuj, zanim nie będziesz pewny/a, że będzie to korzystne.

Odpowiada Artem Shtepenko, Senior Frontend Engineer w Revolut:

Myślę, że należy zacząć od pomiaru czasu ładowania danych, który powinien być jak najszybszy. Aby go przyspieszyć, można użyć renderowania po stronie serwera (SSR). Użytkownik otrzymuje statyczny kod HTML i może korzystać z aplikacji możliwie najszybciej. Ważne jest również użycie GZIP do zminimalizowania pakietu w sieci i połączenia go z HTTP 2, który umożliwia multipleksowanie. Ostatnim, ale równie ważnym czynnikiem powinna być dystrybucja CDN, ponieważ użytkownicy łączą się z różnych części świata.

Odpowiada Adam Bar, Tech Lead & Software Developer w Bright Inventions:

Najbardziej wartościowe metryki są ciężkie do uchwycenia, bo są specyficzne dla aplikacji. Google definiuje koncept “First Meaningful Paint” (FMP), czyli czasu do pierwszego momentu, w którym użytkownik widzi wartościową treść strony, a także “Time to Interactive” (TTI), czyli czasu do pierwszego momentu, kiedy wszystkie inicjalne JavaScripty się załadowały i użytkownik może wejść w interakcję ze stroną. Oba zazwyczaj wymagają ręcznego mierzenia. W praktyce jednak, gdy zaczniemy zwracać uwagę na czas zdarzenia “DOMContentLoaded”, prawdopodobnie i tak “przy okazji” poprawimy FMP oraz TTI.

6. Czy znasz jakieś narzędzia, biblioteki lub techniki automatyzujące lub wspomagające prace nad wydajnością front-endu?

Odpowiada Andrii Los, Senior Frontend Engineer w Revolut:

Przykładowo, do śledzenia szybkości ładowania witryny polecam narzędzie Google PageSpeed. Ponadto Chrome ma zakładkę Audity w swoich narzędziach programistycznych, które odzwierciedlają niektóre funkcje Google PageSpeed. Jeśli mówimy o procesie budowania i innych optymalizacjach, nie ma lepszego narzędzia niż Webpack. Posiada wszystkie potrzebne funkcje, w tym “tree-shaking” (usuwanie nieużywanego kodu), eliminację martwego kodu (kod, który tam jest, używany, ale nigdy nie zostanie uruchomiony), minifikację JS, CSS, HTML, SVG i innych formatów, dynamiczne importowanie, aby zapewnić dostarczenie tylko potrzebnego kodu na pierwszej farbie (tutaj można sprawdzić zasięg użycia kodu w Chrome) i wiele innych.

Innym niesamowitym narzędziem w Webpack jest analizator pakietów webpack, który pomaga w idealny sposób wizualizować pakiety, których używasz w swojej aplikacji, aby w pełni wykorzystać rozmiar pakietu JS.

Ostatnia rada, zawsze warto dostroić ustawienia do swoich potrzeb, ale indywidualne konfiguracje są najtrudniejsze w tworzeniu front-endu. Dlatego zalecamy korzystanie z aplikacji create-react-app i innych narzędzi CLI do budowania aplikacji, aby uprościć wszystko do jednego pakietu, który trzeba od czasu do czasu podbijać. My, w Revolut, wykorzystujemy go do 99% naszych projektów internetowych – chociaż dopracowaliśmy go, aby obsługiwał niektóre wtyczki Babel i zmieniał ESLint – wciąż jest to jednak 99% oryginalny CRA.

Odpowiada Artem Shtepenko, Senior Frontend Engineer w Revolut:

Bardzo użyteczny jest zestaw narzędzi wydajnościowych zebranych w Chrome Dev Tools, które umożliwiają pomiar czasu renderowania za pomocą karty Wydajność. Można ustawić przepustowość procesora, przeanalizować żądanie sieci, użycie pamięci i inne dane. Google PageSpeed ​​dają statystyki dla Twojej strony internetowej. Webpack ma również bardzo dobry zestaw wtyczek, które pozwalają minimalizować (na przykład wtyczkę UglifyJS)/optymalizować/analizować kod. Ponadto nie należy zapominać o wydajności sieci, takiej jak czas ładowania obrazów/skryptów itp. z CDN i miło mieć też obsługę HTTP2 w aplikacji.

Odpowiada Adam Bar, Tech Lead & Software Developer w Bright Inventions:

Sytuacja w tym temacie poprawia się z miesiąca na miesiąc. Króluje Lighthouse, narzędzie od Google’a, obecnie wbudowane w Dev Toolsy w Chromie, a także dostępne na https://web.dev. Lighthouse’a można również uruchamiać z linii komend, przez co może być wpięty w nasz proces Continuous Integration. Jest również szereg serwisów, które pomagają w pomiarach, klasyczny przykład to http://webpagetest.org.


Zdjęcia główne artykułu pochodzi z unsplash.com.

Patronujemy

 
 
Polecamy
Jak ustawić przekierowania w aplikacji Ruby Rack