Angular Tips & Tricks cz. VII

Witam, po niespełna dwóch latach wracamy z kolejną odsłoną Tips & Tricks. Niezmiennie 7 przypadków, startujemy!

1. Debugowanie komponentów w konsoli

Angular w swojej najnowszej 9 wersji wraz z Ivy oferuje nowe api globalnego obiektu ng do debugowania aplikacji w trybie deweloperskim. Pozwala ono m.in. na podejrzenie oraz manipulację stanem naszego komponentu z poziomu konsoli. Dotychczas również mogliśmy korzystać z globalnego obiektu ng, ale nie posiadał on tak szerokiego zestawu metod, jak obecny i nie był zawarty w oficjalnej dokumentacji.

Jedyne co musimy zrobić w celu sprawdzenia stanu naszego komponentu z poziomu konsoli, to:

  1. otworzenie narzędzi developerskich (np. Chrome Devtools)
  2. odnalezienie elementu DOM komponentu w zakładce Elements, a następnie zaznaczenie go
  3. wywołanie następującej komendy w konsoli
    1. Przed Ivy – ng.probe($0).componentInstance
    2. Z wykorzystaniem Ivy – ng.getComponent($0)

Należy zwrócić uwagę, że pod $0 znajduje się obecnie wybrany DOM element z zakładki Elements. W przypadku gdy nie będzie to komponent Angularowy nasza komenda zwróci null. Więcej na temat $0, można przeczytać tutaj.
|

Przewagą nowego api nad starym jest np. łatwość, z jaką możemy uruchomić change detection na naszym komponencie w celu odzwierciedlenia zmian wprowadzonych z poziomu konsoli:

  • Przed Ivy

  • Z wykorzystaniem Ivy


    Wraz z nowym api, pojawiły się też nowe narzędzia t.j SB Angular Inspector, który może oszczędzić Wam wpisywania wspomnianych komend w konsoli.

    2. Ograniczenie change detection dzięki Event  Coalescing

Problem omówimy posługując się prostym przykładem z repozytorium Angulara

Po kliknięciu przycisku, ze względu na event bubbling, obie metody zostaną wywołane, a co za tym idzie, change detection również zostanie uruchomione dwukrotnie. Wraz z  Angularem v9, mamy możliwość instruowania Angulara, aby łączył zdarzenia, co na podstawie naszego przykładu pozwoli nam ograniczyć uruchomienie change detection do jednego. Robimy to ustawiając nową właściwość ngZoneEventCoalescing na true w metodzie bootstrapModule.

Niestety informacji o istnieniu tej flagi na próżno szukać w dokumentacji, mimo iż dodanie jej tam było rekomendowane twórcy tego feature’a 🙂

O tym, jak inaczej z wykorzystaniem zone.js ograniczyć ilość wywoływanych cykli change detection pisaliśmy również w naszym artykule – Angular i zone.js.

3. Użycie const enum zamiast enum

W celu wykazania różnicy pomiędzy tymi deklaracjami enuma musimy zerknąć w kod wynikowy js, dla obydwu podejść

  • enum
    Angular Tips & Tricks
  • const enum
    Angular Tips & Tricks

Jak widać, na przykładzie tak prostego enuma, udało nam się ograniczyć kod wynikowy o 5 linijek. Co przy większej skali może pozytywnie wpłynąć na rozmiar naszego bundle’a.

W większości przypadków const enum zaspokoi nasze potrzeby, aczkolwiek jest jeden przypadek, kiedy na pewno nie możemy go użyć. Ma to miejsce w momencie, gdy planujemy używać wartości naszego enuma w sposób dynamiczny np.iterując się po jego kluczach. Wartości kluczy przy użyciu const są rozstrzygane w momencie kompilacji, później działający już program nie ma do nich dostępu, dlatego iteracja po nich jest niemożliwa.

4. Bezpieczny switch dla union type

Wyobraźmy sobie bardzo powszechny problem:

  • mamy enum reprezentujący wszystkie wartości mogące trafić do naszego switcha
  • mamy switcha, wewnątrz którego chcemy obsłużyć wszystkie klucze enuma

Świetnie, a teraz do naszego enuma dodamy kolejną wartość.

Czy obecnie zostaniemy poinformowani o konieczności obsłużenia nowej wartości wewnątrz naszego switcha? Niestety nie. 

Aby wymusić pokazanie nam tej informacji, musimy dodać klauzulę default wewnątrz której, przypiszemy wartość wybranej opcji do property zatypowanego jako never.

Dzięki temu zabiegowi otrzymujemy następujący komunikat o nieobsłużonym kluczu naszego enuma.

Angular Tips & Tricks

5. Content projection – używanie wielu slotów ng-content z selectem

Podczas tworzenia komponentów Angularowych, często występuje potrzeba transkludowania fragmentu HTML z rodzica do dziecka. Oznacza to, że możemy efektywnie ‘wstrzyknąć’ HTML do templatki dziecka. Aby to osiągnąć użyjemy tagu ng-content jako swego rodzaju placeholder na ‘wstrzykiwaną’ wartość wewnątrz templatki dziecka.

Mniej znanym faktem jest to, że nic nie stoi na przeszkodzie, aby mieć wiele takich placholderów i każdy dedykowany innemu fragmentowi HTML. W tym celu musimy użyć ng-content z dodatkowym atrybutem – select. Akceptuje on wartości podobne do metody document.querySelector, więc możemy selektować np. według taga, atrybutu, klasy CSS lub łącząc ze sobą wszystkie selektory jednocześnie.

  • Przykład templatki rodzica

  • Przykład templatki dziecka

  • Wynikowy HTML dziecka

6. Analiza bundle’a aplikacji z wykorzystaniem webpack-bundle-analyzer

Twoja aplikacja ładuje się wolno i szukasz sposobu jak ją przyspieszyć? Weryfikacja bundle’a aplikacji jest dobrym punktem wyjścia podczas próby usprawnienia wydajności. Webpack bundle analyzer za pomocą przejrzystej wizualizacji pozwala zobaczyć ile miejsca zajmują poszczególne paczki w naszym bundle’u oraz zidentyfikować niewykorzystywane bądź zbędne zależności.

webpack bundle analyzer zoomable treemap
(źródło:https://github.com/webpack-contrib/webpack-bundle-analyzer)

7. Unikaj używania metod na template

Trzeba przyznać, że używanie metod na templatce jest wygodnym i szybkim rozwiązaniem, ale niestety może doprowadzić do poważnych problemów z wydajnością naszej aplikacji. Dzieje się tak dlatego, że metoda na templatce będzie wywoływana przy każdym cyklu change detection.

Zalecane są następujące alternatywy w sytuacji gdy wartość którą chcemy wyświetlić jest wyliczana:

  • manualne kalkulowanie property wyświetlanej na templatce w momencie, gdy wartości od których ona zależy ulegną zmianie.
  • użycie pure pipes, które, zostaną wywołane tylko wtedy kiedy wartość wejściowa lub jej referencja ulegnie zmianie. 
  • skorzystać z memoizacji. Kiedy wprowadzimy ponownie tę samą wartość wejściową do naszej memoizowanej funkcji, zwraca ona wartość zapisaną w cache zamiast ponownie uruchamiać funkcję, zwiększając w ten sposób wydajność.

Więcej na temat pure pipes oraz memoizacji znajdziecie w artykule – Angular performance tips.

W celu dokładniejszego zrozumienia problemu zachęcam Cię do zapoznania się z jednym z dwóch poniższych artykułów

 

To by było na tyle dzięki!

PS dajcie znać w komentarzach, które sztuczki z tej serii tips & tricks znaliście, a które okazały się dla was czymś nowym.

One Comment

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *