1 of 70

Angular alkalmazások teljesítménynövelése

Kiss Balázs 2023.

1

2 of 70

Rólam

Kiss Balázs

  • BME VIK Mérnök-informatikus MSc. /2015/
  • Szoftver tervezés, fejlesztés és oktatás, konzultáns, �senior dev, team lead, contractor pozícióban (Webváltó)
  • Webes frontend alkalmazások tervezése, fejlesztése, frontend-fókusz
  • NAV, MÁK, TIBEK, Vodafone, I-Cell, IVU, AGCO, stb.

2

3 of 70

Tartalomjegyzék:

  1. A probléma
  2. Auditálás
  3. Angular performance tuning
  4. További lehetőségek

3

4 of 70

  1. A probléma:
  1. A webappok komplexitásnövekedése miatt a performancia sérül �(lassul az app)
  2. Az Angular a “legkövérebb” JS alapú framework a piacon
    • Ő lenne a leglassabb is?
  3. Hogyan tehetjük gyorsabbá az Angular alkalmazásunkat?
    • Illetve Framework független tanácsok :)

4

5 of 70

  1. A megoldás:
  • Webes technológiai trükkök
  • Angular eszközök pontos ismerete
  • Angular performance tuning
  • Külső segédeszközök bevetése

Disclaimer: elég sok guide van fent a neten.

Bottom line: tapasztalat, józan ész, prog.tudás, JS, TS, HTML, CSS, Web, és végül Angular ismerete

5

6 of 70

  1. Szemlélet
  • Teljes eszköztárat használjuk fel
  • Értsük meg, melyik rétegben tudjuk a legjobb megoldást elérni

6

Programozói tudás

OSI, Web API réteg

EcmaScript, HTML, CSS

Framework

Segédkönyvtárak

Architekturális döntések

7 of 70

  • Szemlélet
  • Teljes eszköztárat használjuk fel
  • Értsük meg, melyik rétegben tudjuk a legjobb megoldást elérni

Honnan tudjam, mit nem tudok?

https://roadmap.sh/frontend

(ha csak egy dolgot jegyzel meg ma)

7

Programozói tudás

OSI, Web API réteg

EcmaScript, HTML, CSS

Framework

Segédkönyvtárak

Architekturális döntések

8 of 70

  1. Gyors app !== Angular?

8

9 of 70

2. Auditálás

9

10 of 70

2. Hogyan mérjük a performanciát?

Webalkalmazás auditálása = fancy word a checklisteken végigmenésre

  • Architekturális szinten
    • Good luck (tapasztalat)
  • Kódszinten
    • Pl. app verzió, security problémák, lintelés
  • Futó alkalmazás szintjén
    • Betöltési idő, performancia metrikák
  • SEO
    • Nem mindenhol fontos
    • Amúgy Good luck (tapasztalat)
  • Design szinten
    • Good luck (tapasztalat)

10

11 of 70

2. Hogyan mérjük a performanciát?

Webalkalmazás auditálása

  • Architekturális szinten
    • Good luck (tapasztalat)
  • Kódszinten
    • Pl. app verzió, security problémák, lintelés
  • Futó alkalmazás szintjén
    • Betöltési idő, performancia metrikák
  • SEO
    • Nem mindenhol fontos
    • Amúgy Good luck (tapasztalat)
  • Design szinten
    • Good luck (tapasztalat)

11

Ezekre vannak toolok, amiket már kezdőként is használhatunk (és haladóként is illik)

12 of 70

2. Hogyan mérjük a performanciát?

Webalkalmazás auditálása = fancy word a checklisteken végigmenésre

  • Architekturális szinten
    • Good luck (tapasztalat)
  • Kódszinten
    • Pl. app verzió, security problémák, lintelés
  • Futó alkalmazás szintjén
    • Betöltési idő, performancia metrikák
  • SEO
    • Nem mindenhol fontos
    • Amúgy Good luck (tapasztalat)
  • Design szinten

12

Online toolok, leírások, tippek böngészését javaslom, Google, Apple, Mozzilla stb.

13 of 70

2. Kód audit eszközök

Angular esetén javasolt kódminőség javító eszközök:

  • ESlint
    • Minden JS alapú webappnál kötelező kvázi
    • TypeScript kiegészítések pluginnel részei
    • Régen: Codelyzer, TSLint, ezeket már lecseréltük!
  • Unit tesztek
    • Mivel Angular esetén integrációs tesztekről van szó, sok performance nüansz-t kiszűrhetnek

Megjegyzés: Prettier és társai kódformázás, nem szigorúan kódminőség-javító hatásúak, de fontosak

13

14 of 70

2. Kód audit eszközök #2

  • Webpack Bundle Analyzer
    • Vizualizációs eszköz, mekkora lesz a végső JS bundle
    • Segít optimalizációs lehetőségeket találni, első sorban méretcsökkentésre

14

15 of 70

2. Kód audit eszközök #2

Bundle Analyzer Demo https://github.com/webpack-contrib/webpack-bundle-analyzer

  1. $ npm install --save-dev webpack-bundle-analyzer
  2. $ ng build --stats-json
  3. $ npx webpack-bundle-analyzer dist/<projektnév>/stats.json
  4. $$$

15

Cheat sheet:

Stat: direkt méret

Parsed: minification után

16 of 70

2. Kód audit eszközök #2

  • Webpack Bundle Analyzer
    • Vizualizációs eszköz, mekkora lesz a végső JS bundle
    • Segít optimalizációs lehetőségeket találni, első sorban méretcsökkentésre
  • Lehetséges javítások:
    • Teles lib helyett csak részegységeit behúzni
    • “Jobban” behúzni egy implicit dependenciát (“shakeable”)
    • Lazy-load határokat kitalálni

Bővebben: https://blog.jakoblind.no/webpack-bundle-analyzer/

16

17 of 70

2. Kód audit eszközök #3

  • Source Map explorer
  • Import Graph Visualizer

17

18 of 70

2. Kód audit eszközök: bónusz

  • Code review tools
    • IntelliJ
    • VSCode

  • Quick fix

18

19 of 70

2. Kód audit eszközök: bónusz

  • Code review tools
    • IntelliJ
    • VSCode

  • Quick fix

    • ChatGPT?

19

20 of 70

2. Webapp metrikák

Betöltés és működés mérése… több megközelítés is kering

Egy jó (újabb) kezdeményezés: https://www.w3.org/webperf/ és https://web.dev/i18n/en/vitals/ felhasználó központúság

  • Largest Contentful Paint: a legnagyobb kép vagy szöveg megjelenítésének időtartama (80%-ban kép)
  • First Input Delay: az első DOM elemek megjelenése és a javascript inicializáció közötti idő
  • Cumulative Layout Shift: A betöltés közben megjelenő DOM elemek miatt történő “ugrálások” közös mérőszáma

20

21 of 70

2. Futó alkalmazás audit eszközök

Ezek már egy futó alkalmazás metrikáit gyűjtik: valódi performancia

  • Google Lighthouse
  • Google PageSpeed
    • Google Cloud-ból hosztolt, kicsit szerényebb, csak performance metrikák
    • https://pagespeed.web.dev/

21

22 of 70

2. Futó alkalmazás audit eszközök

(folyt.)

  • WebPageTest
    • Open source + fizetős szolgáltatás, https://www.webpagetest.org
  • GTmetrix
    • Fizetős szolgáltatás, https://gtmetrix.com/
  • Pingddom
    • Fizetős, UX-re hegyezve https://www.pingdom.com/

És még biztos vagyok benne hogy van kismillió…

Bónusz: Google Analytics

Bónusz2: Schema.org és társai

22

23 of 70

2. Google Lighthouse

  • (szerintem) a legjobb tool
  • Performance Audit
  • A11y, Best Practices, SEO, PWA audit
  • Közvetlenül a saját gépedről futtatható
  • Nézzük meg :)

23

24 of 70

3. Angular eszközök

24

25 of 70

3. Legfontosabb Angular eszközök

Build optimalizáció:

  1. Lazy Loading
  2. Server Side Rendering

Runtime optimalizáció:

  1. Preloading
  2. Change Detection technikák
  3. Function bind elkerülése
  4. ExpressionChangedAfterItHasBeenCheckedError
  5. TrackBy Function
  6. Virtual Scrolling
  7. Resolver, Intializer
  8. Reactive pattern RxJS-sel
  9. App Shell

25

26 of 70

3.1. Build & Bundle

Lazy-loading modules

https://angular.io/guide/lazy-loading-ngmodules

Tehát csak igény esetén töltjük be őket: pl. amíg nem navigálunk el a felhasználó profil oldalára, addig az ezzel kapcsolatos funkciókat nem töltjük be.

  • Előny1: Gyorsítja az app működését
  • Előny2: Csökkenti a bundle méretét
  • Előny3: Valódi egységbezárás, újrafelhasználhatóságot erősít

26

27 of 70

3.1. Build & Bundle

Lazy-loading modules

https://angular.io/guide/lazy-loading-ngmodules

Tehát csak igény esetén töltjük be őket: pl. amíg nem navigálunk el a felhasználó profil oldalára, addig az ezzel kapcsolatos funkciókat nem töltjük be.

  • Előny1: Gyorsítja az app működését
  • Előny2: Csökkenti a bundle méretét
  • Előny3: Valódi egységbezárás, újrafelhasználhatóságot erősít

Bónusz: mikrofrontendek

  • Több előadás is volt már a témában

27

28 of 70

3.1. Build & Bundle

Lazy-loading modules

https://angular.io/guide/lazy-loading-ngmodules

Tehát csak igény esetén töltjük be őket: pl. amíg nem navigálunk el a felhasználó profil oldalára, addig az ezzel kapcsolatos funkciókat nem töltjük be.

  • Előny1: Gyorsítja az app működését
  • Előny2: Csökkenti a bundle méretét
  • Előny3: Valódi egységbezárás, újrafelhasználhatóságot erősít

Bónusz: mikrofrontendek

  • Több előadás is volt már a témában

28

Bónusz2: Standalone components

  • A komponesek (service-ek, pipe-ok stb.) is lazy-loadedek lehetnek

29 of 70

3.1. Standalone xy.

Lazy load-olható komponensek (angular v14 óta)

  • Lazy-load komponensek / service-ek stb.
  • Konfig kb. mint unit tesztelésnél, csak itt komponens szinten
  • kézzel fel kell oldani a függőségeket

Bootstrappelhető, Modulokat hivatkozhat be, modulok is bemelhetőek (smooth átállás)

29

30 of 70

3.2. Build & Bundle

Server Side Rendering�https://web.dev/rendering-on-the-web/

Ötlet: rendereljük le a weboldalt úgy mint régen a szerveroldalon, és azt gyorsabban vissza tudjuk adni, mint az SPA-nkat. Mindkettőt adjuk oda, és az SPA vegye át az irányítást ha elindult

https://angular.io/guide/universal (Angular Universal)

  • Más megoldások is vannak: pl. https://prerender.io/
  • Előny1: SEO problémák a crawlerek miatt
  • Előny2: gyorsítja az betöltési időket, FCP
  • Hátrány: “átadni a gyeplőt” bonyolult kérdés (rehydration)
  • Hátrány2: szükséges egy szerver működés

30

31 of 70

4.1. Preloading

Nem összekeverendő a LazyLoading-gal

  • Ez runtime optimalizáció!

https://danielk.tech/home/complete-angular-performance-guide

31

32 of 70

4.2. Change Detection

  • Érdemes megérteni legalább magas szinten
    • Nincsen “angular motor”, a saját kódunk van egybefordítva a lib-bel

https://www.youtube.com/watch?v=S0o-4yc2n-8

32

33 of 70

4.2. Compiler

TS -> JS, + dekorátorok -> előállítja a Module és Component Definition-öket

34 of 70

4.2. Change Detection

34

35 of 70

4.2. Change Detection

Az angular-nak fáj-e?

  • Sok binding?
    • Elvileg nem, nincs rendering közvetlenül
    • Változók nincsenek copy-zva, referenciával vannak megosztva egymás között
  • Sok komponens?
    • Nem, hisz függvénydefiníciók lesznek, nem valami robosztus nagy objektumok
    • Nem baj a sok fájl, azért van a build folyamat
    • Ráadásul lazy load-dal gyorsítjuk a működést

35

36 of 70

4.2. Change Detection

Az angular-nak fáj-e?

  • Sok binding?
  • Sok komponens?

Az Angular nagy problémája a felesleges ChangeDetection futtatás költsége.

Mélyebb megismeréshez: https://indepth.dev/posts/1053/everything-you-need-to-know-about-change-detection-in-angular

36

37 of 70

4.2. ChangeDetection optimalizálás

Szintek:

  1. ChangeDetectionStrategy.OnPush

Change Detection csak akkor fog futni, ha a komponens inputjai változnak (vagy esemény történik a komponensben vagy gyerekeiben)

  • Még ott van a this.ref.detectChanges() is, ha bajban lennénk

Általában érdemes használni, de vannak benne buktatók!

  • CD detach

A changedetector ref-fel le is lehet teljesen állítani a komponens figyelését:

  • detach()
  • detectChanges()
  • markForCheck()
  • reattach()

37

constructor(private ref: ChangeDetectorRef) {

this.ref.detach();

}

38 of 70

4.2. ChangeDetection optimalizálás

3. Zone.js: async folyamatokra akasztott hook-ok, a CD-triggerelésére. Minden hívásra “ráakaszkodik”

  • Gyakran ez nagy overhead
  • UI frissítéssel így várhatunk �Pl. a betöltés végéig

4. WebWorker api

Valódi szeparált JS szál,

Background processzekhez, mobilos feladatokhoz, de jól jöhet weben is

38

constructor(private ngZone: NgZone) {

this.ngZone.runOutsideAngular(() => {

// this will not trigger change detection

setInterval(() => doSomething(), 100)

});

}

39 of 70

4.2. Bónusz #2: Signals

Zone.js:

  • Eseménykezelés segéd lib
  • Minden eseményt elkap, erre van “rákötve” a ChangeDetection (meg hibakezelés, stb.)
  • Ezt tervezik lecserélni egy “natív” megoldással
    • Példa: https://www.solidjs.com/
    • Ennek az “Angularos” verzióját készítik éppen
    • Signal: egy wrapper, “observable” szerű, esemény lánc. Műveletek, (pl. Kettő signal összekötése). SolidJS-ben a változás “Subject” szerűen triggereli a re-renderinget
  • Miért?
    • A zone.js change detection csekkolás időigényes: itt csak az éled fel, ami ténylegesen változik (még egy szinttel kevesebb ellenőrzés)

https://dev.to/this-is-angular/angular-signals-everything-you-need-to-know-2b7g

39

40 of 70

4.3. Tipik hiba: Function Bind

https://stackblitz.com/edit/angular-sotet-oldal-2

  • Lehet használni, de legyen mellékhatásoktól mentes.
  • Dev mode-ban eggyel több check van
  • Komplex esetekben exponenciális növekedés

40

{{ getResult() }}

getResult() {

return this.sum;

}

41 of 70

4.3. Tipik hiba: Function Bind

https://stackblitz.com/edit/angular-sotet-oldal-2

  • Lehet használni, de legyen mellékhatásoktól mentes.
  • Dev mode-ban eggyel több check van
  • Komplex esetekben exponenciális növekedés

Megoldás: propertybind, ahol lehet (vagy pure RxJS…)

Pure pipes:

https://stackblitz.com/edit/angular-sotet-oldal-2-purepipe

További példák másik előadásban:

41

{{ getResult() }}

getResult() {

return this.sum;

}

42 of 70

4.4. Tipik hiba #2: ExpressionChangedAfterItHasBeenCheckedError

  • ChangeDetection kiváltódásakor futhatunk bele.

Csak DEV módban jön elő

  • Minek foglalkozni vele?
  • Inkonzisztencia, race condition

43 of 70

4.5. Track By

Minden esemény (egér mozgás, animációk stb.) kiváltja az újra renderelést

  • Ezzel segíthetünk szűrni, hogy csak ha az adott property valóban módosul, kell újra renderelni (react key?)

https://stackblitz.com/edit/angular-sotet-oldal-4-javtva

43

<tr *ngFor="let item of tableData; trackBy:trackByCode">

<td>{{ item.code }}</td>

<td>{{ item.name }}</td>

<td>{{ item.price | currency }}</td>

</tr>

44 of 70

4.6. CDK, VirtualScroll, InfiniteScroll

Angular Material CDK része az eszköztár

44

45 of 70

4.6. CDK, VirtualScroll, InfiniteScroll

45

overlay

dialog

snackbar

menu

tooltip

autocomplete

tabs

stepper

dynamic content

focus

trap

sidenav

dialog

CDK

46 of 70

4.6. CDK, VirtualScroll, InfiniteScroll

Angular Material CDK része az eszköztár

  • Amúgy itt is van még pár érdekes

Két optimalizálás:

  1. Letöltött elemek scroll állapot (event) alapján (REST hívás, RxJS segít)
  2. Renderelendő elemek egy listában a frontenden (DOM művelet)

46

47 of 70

4.7. Angular Resolver

  • Routing esetén
    • Tipikus eset: valamit szeretnék letölteni MIELŐTT renderelem az oldalt
    • Kérdés: mikor akarom a “loader” animációt? Navigáció előtt v. után?
  • Összevont betöltés több sub-route esetén pl.
  • Teljes app indulás előtt: APP_INITIALIZER

47

48 of 70

4.8. RxJS

  • “Be kell seggelni”, good luck
  • Reaktív pattern (A+B=C vs. A+B=C)

Csomó hiba a Reaktív, dekleratív gondolkodásmód hiányából (szekvenciális, imperatív módon használva)

Példa1:

https://medium.com/@paynoattn/3-common-mistakes-i-see�-people-use-in-rx-and-the-observable-pattern-ba55fee3d031

48

49 of 70

4.8. RxJS

https://angular.io/guide/rx-library

  • Operátorok, hibakezelés, saját logika beiktatása

Evolúció “csúcsa”: |async pipe-ig “kicsurgatni” mindent

49

@Component({

selector: 'test',

template: `

<div *ngFor="let user of userlist">

{{ user?.name }}

{{ user?.email }}

</div>

`

})

export class MyExampleComponent {

const userList: any[]

constructor(http: HttpClient) {

this.load();

}

getUserList() {

return this.http.get(apiUrl);

}

load() {

this.getUserList().subscribe(user => {

this.userList = user;

})

};

}

@Component({

selector: 'test',

template: `

<div *ngFor="let user of userlist | async">

{{ user?.name }}

{{ user?.email }}

</div>

`

})

export class MyExampleComponent {

const userList: Observable<any>

constructor(http: HttpClient) {

this.load();

}

getUserList() {

return this.http.get(apiUrl);

}

load() {

this.userList = this.getUserList().subscribe();

}

50 of 70

4.8. RxJS Time

Pl. DebounceTime:

És még van pár hasonló alternatíva (throttle, audit, sample stb. )

https://dev.to/rxjs/debounce-vs-throttle-vs-audit-vs-sample-difference-you-should-know-1f21 )

50

51 of 70

4.9. App Shell

A technika Performancia + UX (de inkább UX) trükk

  • Előre megjelenítünk egy statikus shell-t,
  • Azt később populáljuk tartalommal

Angular-ban:

  • Pl. Header, Footer, Body
  • Ez kívül kerül az app-on, SSR lényegében

https://angular.io/guide/app-shell

Skeleton-screen, Shimmer Effect

51

52 of 70

További lehetőségek

52

53 of 70

5.1. Dev szerver csere

Fejlesztési élmény javítása (nem mindig az angular a hibás, lehet vas kell a gitlab-otok alá…)

  • esbuild
    • Go based
    • Sokkal gyorsabb
    • Angular 15-től
  • Nx
    • Angular CLI extension, monorepo
    • Csak a változások renderelése

53

54 of 70

Nálam:

54

original: 17246 ms

esbuild: 6747 ms

original: 13680 ms

esbuild 7843 ms

47663ms

15.317

55 of 70

5.2. Cache-elés

  1. Programkódból, kézzel
    1. Csúnya megoldás*: te írod, Interceptor segítségével

55

56 of 70

5.2. Cache-elés

  • Programkódból, kézzel
    • Csúnya megoldás*: te írod, Interceptor segítségével
    • Szép megoldás*: RxJS :)

https://tomastrajan.medium.com/the-best-new-way-to-cache-api-responses-with-angular-rxjs-5cbc05d12f10

56

57 of 70

5.2. Cache-elés

  • Programkódból, kézzel
    • Csúnya megoldás*: te írod, Interceptor segítségével
    • Szép megoldás*: RxJS :)
  • Segédkönytárral
    • Pl. ts-Cacheable

57

58 of 70

5.2. Cache-elés

  • Programkódból, kézzel
    • Csúnya megoldás*: te írod, Interceptor segítségével
    • Szép megoldás*: RxJS :)
  • Segédkönytárral
    • Pl. ts-Cacheable

*: szerintem :)

58

59 of 70

5.3. App felosztása

  • Csak átlinkelünk

  • iFrame beágyazás

  • Web komponensek

  • Library / Monorepo / Microfrontend

59

Nem túl összefüggő appok

60 of 70

5.4. CQRS modell

https://martinfowler.com/bliki/CQRS.html

  • Command Query Responsibility Segregation
    • lényege: különválasztjuk a state kiolvasását és a �state módosítását egymástól.

Kvázi “CRUD”-nak tekintjük a state-et �(Create, Read, Update, Delete)

ugyanazok az előnyök

  • elosztott működés
  • szinkronizáció, versenyhelyzetek -
  • skálázhatóság

És ez evolválódik tovább

60

61 of 70

5.4. CQRS (Redux) modell

https://martinfowler.com/bliki/CQRS.html

  • Command Query Responsibility Segregation
    • lényege: különválasztjuk a state kiolvasását és a �state módosítását egymástól.

Kvázi “CRUD”-nak tekintjük a state-et �(Create, Read, Update, Delete)

ugyanazok az előnyök

  • elosztott működés
  • szinkronizáció, versenyhelyzetek -
  • skálázhatóság

És ez evolválódik tovább

61

62 of 70

5.4. State kezelés könyvtárai

  • “Design for Immutability”, “redux” like

Ha az Angular-os vonalvezetés nem volna elég

https://ordina-jworks.github.io/angular/2018/10/08/angular-state-management-comparison.html

62

63 of 70

5.5. Image directive

NgOptimizedImage

LCP érték miatt

Néhány feature:

  • Intelligens Lazy Load
    • Ha nem látszik, lazy-loadolható
    • Priorizálás
  • CDN api
  • Hibaüzenetek
    • Best practices

63

64 of 70

5.6. RxJS hasznos linkek #2

64

65 of 70

5.7. UI Könyvtárak

65

Clarity

Lightning

ngBootstrap

66 of 70

5.8. AoT, Ivy

Rendering típusok:

  • Just In Time (JIT):
    • Runtime compile
  • Ahead-of-time Compilation (AoT)
  • Build time compile, egyből indul az app

Ivy:

  • Új rendering engine, Angular 9 óta (előző ViewEngine), default AoT compiler

Nem kell vele foglalkozni, Angular 9 óta default dev, és prod módban is. (upgradeljetek!)

66

67 of 70

5.9. Bónusz: ha nem értek valamit

67

68 of 70

5.10. Angular Checklist

https://github.com/typebytes/angular-checklist

  • Félve osztom meg: nem tudom mikor ugorják már meg végre az update-et

68

69 of 70

5.11. Bónusz

Az előadás közben, a nézők által élőben küldött egyéb hasznos linkek:

69

70 of 70

Köszönöm a figyelmet!

Kérdésed van? Keress bátran:

  • balazs.kiss@webvalto.hu
  • HWSW Discord

70