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