Slide 1

Slide 1 text

Angular Performance So zünden Sie den Turbo Christian Liebel @christianliebel Consultant

Slide 2

Slide 2 text

What you cannot expect - Web performance in general (e.g. HTTP/2, compression, JS tweaks, CSS) - Deep-dive into performance metrics - 1:1 support What you can expect - Angular-specific performance measures - Common performance pitfalls and how to avoid them - Hands-on exercies for everyone Angular Performance So zünden Sie den Turbo Expectations

Slide 3

Slide 3 text

Hello, it’s me. Angular Performance So zünden Sie den Turbo Christian Liebel Twitter: @christianliebel Email: christian.liebel @thinktecture.com Angular & PWA Slides: thinktecture.com /christian-liebel

Slide 4

Slide 4 text

Angular Performance So zünden Sie den Turbo Timetable 09:00–10:30 Part I 10:30–11:00 Coffee break 11:00–12:30 Part II

Slide 5

Slide 5 text

Requirements for hands-on labs: Node.js + Angular CLI + Google Chrome + Editor Angular Performance So zünden Sie den Turbo

Slide 6

Slide 6 text

53% der Benutzer springen ab, wenn eine Website länger lädt als 3 Sekunden. (DoubleClick, Google) Für jede Sekunde Ladezeit springen je 10% der Benutzer ab. (BBC) Bessere Performance = geringere Absprungrate Angular Performance So zünden Sie den Turbo

Slide 7

Slide 7 text

Runtime Performance Bundling Lazy Loading Preloading Strategies Server-Side Rendering Service Worker Angular Performance So zünden Sie den Turbo Agenda Change Detection Basics Zone.js & NgZone Change Detection Strategies Change Detector Async Pipe Load Time Performance

Slide 8

Slide 8 text

Don’t over-optimize. Angular Performance So zünden Sie den Turbo First Rule

Slide 9

Slide 9 text

Reduce required computations during runtime - calculations - painting - layouting - … Today: Angular-specific performance topics Angular Performance So zünden Sie den Turbo Runtime Performance

Slide 10

Slide 10 text

Runtime Performance Bundling Lazy Loading Preloading Strategies Server-Side Rendering Service Worker Angular Performance So zünden Sie den Turbo Agenda Change Detection Basics Zone.js & NgZone Change Detection Strategies Change Detector Async Pipe Load Time Performance

Slide 11

Slide 11 text

Hi Angular! Basics // app.component.html

Hi {{ title }}!

// app.component.ts @Component({ /* … */ }) export class AppComponent { title = 'Angular'; } Angular Performance So zünden Sie den Turbo Change Detection

Slide 12

Slide 12 text

Basics // app.component.html

Hi {{ title }}!

Update // app.component.ts @Component({ /* … */ }) export class AppComponent { title = 'Angular'; update() { this.title = 'Foo'; } } Angular Performance So zünden Sie den Turbo Change Detection Hi Foo! Hi Angular! Update

Slide 13

Slide 13 text

Basics Change detection… - is the magical part of Angular that makes data binding “just work” - is a very handy feature that helps a lot, but it can also work against you - is strongly related to Angular application performance Angular Performance So zünden Sie den Turbo Change Detection

Slide 14

Slide 14 text

Component Tree AppComponent NavComponent ContentComponent ListComponent Angular Performance So zünden Sie den Turbo Change Detection

Slide 15

Slide 15 text

Change Detector Tree AppComponent NavComponent ContentComponent ListComponent Angular Performance So zünden Sie den Turbo Change Detection AppComponent CD NavComponent CD ContentComponent CD ListComponent CD CHANGE

Slide 16

Slide 16 text

Change Detector detectChanges() Called when an event has occured and bindings should be checked Angular Performance So zünden Sie den Turbo Change Detection this.title = 'Foo';

Hi {{ title }}!

Slide 17

Slide 17 text

Per default, each change in your application leads to… - A single CD cycle - From top to bottom (all components) - Unidirectional (no cycles allowed) Angular Performance So zünden Sie den Turbo Change Detection DEMO

Slide 18

Slide 18 text

First findings Reduce duration of a change detection cycle - Reduce amount of bindings (e.g. grids: virtual scrolling via CDK) - Avoid binding to (computationally intensive) getters or functions Keep CD cycle < 16 ms! Angular Performance So zünden Sie den Turbo Change Detection

Slide 19

Slide 19 text

Profiling // main.ts platformBrowserDynamic().bootstrapModule(AppModule).then(module => enableDebugTools(module.injector.get(ApplicationRef).components[0])); Execute ng.profiler.timeChangeDetection() to measure the duration of a change detection run (500ms or 5 change detection cycles) Angular Performance So zünden Sie den Turbo Change Detection

Slide 20

Slide 20 text

Command Line: ng new perf-demo --routing --style=css // src/main.ts platformBrowserDynamic().bootstrapModule(AppModule).then(module => enableDebugTools(module.injector.get(ApplicationRef).components[0])); DevTools Console: ng.profiler.timeChangeDetection() Angular Performance So zünden Sie den Turbo Change Detection EX #1

Slide 21

Slide 21 text

Runtime Performance Bundling Lazy Loading Preloading Strategies Server-Side Rendering Service Worker Angular Performance So zünden Sie den Turbo Agenda Change Detection Basics Zone.js & NgZone Change Detection Strategies Change Detector Async Pipe Load Time Performance

Slide 22

Slide 22 text

How to detect a change? AppComponent NavComponent ContentComponent ListComponent Angular Performance So zünden Sie den Turbo Zone.js AppComponent CD NavComponent CD ContentComponent CD ListComponent CD CHANGE

Slide 23

Slide 23 text

A look at Angular’s dependencies "dependencies": { "@angular/common": "~10.0.14", "rxjs": "~6.5.5", "tslib": "^2.0.0", "zone.js": "~0.10.3" }, Zone.js So zünden Sie den Turbo Angular Performance

Slide 24

Slide 24 text

Overview Provided by the Angular team Open-source https://github.com/angular/zone.js 1. Provides an execution context for asynchronous JavaScript 2. A meta-monkey patch Zone.js So zünden Sie den Turbo Angular Performance

Slide 25

Slide 25 text

Execution Context function main() { // const start = performance.now(); a(); setTimeout(b, 0); c(); // const stop = performance.now(); // const ms = stop - start; } Zone.js So zünden Sie den Turbo Angular Performance

Slide 26

Slide 26 text

Execution Context Oversimplified Zone.run(main); onZoneEnter(); function main() { a(); setTimeout(b, 0); c(); } onZoneLeave(); Zone.js const orig = window.setTimeout; window.setTimeout = (c, t) => { orig(() => { onZoneEnter(); c(); onZoneLeave(); }, t); }; So zünden Sie den Turbo Angular Performance

Slide 27

Slide 27 text

Execution Context Debugging Pending asynchronous tasks are known Profiling Measuring performance (Google Web Tracing Framework) Mocking/Testing Hooks beforeTask, … Zone.js So zünden Sie den Turbo Angular Performance

Slide 28

Slide 28 text

A Meta-Monkey Patch Zone.js setTimeout setInterval geolocation.getCurrentPosition XMLHttpRequest PromiseRejectionEvent requestAnimationFrame click focus mousemove addEventListener So zünden Sie den Turbo Angular Performance

Slide 29

Slide 29 text

NgZone Angular Performance So zünden Sie den Turbo Zone.js current (global) zone NgZone Angular boot

Slide 30

Slide 30 text

NgZone NgZone catches asynchronous operations from the Angular app When no tasks are remaining for the current VM turn, the NgZone will trigger a change detection cycle (tick) Angular Performance So zünden Sie den Turbo Zone.js NgZone setTimeout setInterval onclick Detect changes Detect changes Detect changes

Slide 31

Slide 31 text

Change Detection Trigger https://github.com/angular/angular/blob/master/packages/core/src/application_ref.ts Angular Performance So zünden Sie den Turbo Zone.js NgZone.onMicrotaskEmpty ApplicationRef.tick() view1.detectChanges() view2.detectChanges() viewN.detectChanges()

Slide 32

Slide 32 text

Common Pitfalls Long CD cycles in combination with high-frequency events - mousemove - scroll - requestAnimationFrame - setInterval with short intervals (clocks!) Angular Performance So zünden Sie den Turbo Zone.js DEMO

Slide 33

Slide 33 text

NgZone Zone.js current (global) zone NgZone rAF Detect changes rAF Detect changes rAF Detect changes rAF Detect changes So zünden Sie den Turbo Angular Performance

Slide 34

Slide 34 text

NgZone Opt-Out constructor (ngZone: NgZone) { ngZone.runOutsideAngular(() => { // runs outside Angular zone, for performance-critical code ngZone.run(() => { // runs inside Angular zone, for updating view afterwards }); }); } Zone.js So zünden Sie den Turbo Angular Performance ! View and model can get out of sync! DEMO

Slide 35

Slide 35 text

NgZone Opt-Out // app.component.ts get title() { console.log('CD'); return 'title'; } ngOnInit() { requestAnimationFrame(() => this.ngOnInit()); // this._ngZone.runOutsideAngular(() => request…); } constructor(private _ngZone: NgZone) {} Angular Performance So zünden Sie den Turbo Zone.js EX #2

Slide 36

Slide 36 text

NgZone Zone.js current (global) zone NgZone rAF rAF rAF rAF So zünden Sie den Turbo Angular Performance

Slide 37

Slide 37 text

Disable Patches (polyfills.ts) (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames Angular Performance So zünden Sie den Turbo Zone.js ! View and model can get out of sync!

Slide 38

Slide 38 text

Event Coalescing
Test
// main.ts platformBrowserDynamic().bootstrapModule(AppModule, { ngZoneEventCoalescing: true }); Angular Performance So zünden Sie den Turbo Zone.js ! App behavior may change! CHANGE CHANGE Coalescing

Slide 39

Slide 39 text

Disable Zone (= disable async change detection!) platformBrowserDynamic().bootstrapModule(AppModule, { ngZone: 'noop' }); constructor(applicationRef: ApplicationRef) { applicationRef.tick(); // trigger CD yourself } Angular Performance So zünden Sie den Turbo Zone.js ! View and model can get out of sync!

Slide 40

Slide 40 text

Runtime Performance Bundling Lazy Loading Preloading Strategies Server-Side Rendering Service Worker Angular Performance So zünden Sie den Turbo Agenda Change Detection Basics Zone.js & NgZone Change Detection Strategies Change Detector Async Pipe Load Time Performance

Slide 41

Slide 41 text

Overview Default Uses Zone.js for detecting changes and updates bindings OnPush Restricts change detection to changes of @Input parameters Angular Performance So zünden Sie den Turbo Change Detection Strategies AppComponent CD NavComponent CD ContentComponent CD ListComponent CD AppComponent CD NavComponent CD ContentComponent CD ListComponent CD OnPush

Slide 42

Slide 42 text

OnPush @Component({ selector: 'my-component', template: '{{ foo }}', changeDetection: ChangeDetectionStrategy.OnPush }) export class MyComponent { @Input() public foo: string; } Change detection only reacts to changes of @Input parameters Angular compares the values passed to an @Input parameter (newValue === oldValue). If you are passing objects, make sure to pass in new instances! Angular Performance So zünden Sie den Turbo Change Detection Strategies ! View and model can get out of sync! DEMO

Slide 43

Slide 43 text

Immutable.js to the rescue Immutable.js is a library that does not update data in place, but yields updated data instead https://facebook.github.io/immutable-js/ const map1 = Immutable.Map({ a: 1, b: 2, c: 3 }); const map2 = map1.set('b', 50); map1.get('b'); // 2 map2.get('b'); // 50 map2.toObject(); // { a: 1, b: 50, c: 3 } Change Detection Strategies So zünden Sie den Turbo Angular Performance

Slide 44

Slide 44 text

// app.component.ts @Component({ changeDetection: ChangeDetectionStrategy.OnPush }) /* … */ ngOnInit() { requestAnimationFrame(() => this.ngOnInit()); // this._ngZone.runOutsideAngular(() => request…); } Angular Performance So zünden Sie den Turbo Change Detection Strategies EX #3

Slide 45

Slide 45 text

Runtime Performance Bundling Lazy Loading Preloading Strategies Server-Side Rendering Service Worker Angular Performance So zünden Sie den Turbo Agenda Change Detection Basics Zone.js & NgZone Change Detection Strategies Change Detector Async Pipe Load Time Performance

Slide 46

Slide 46 text

OnPush & Detecting Changes What to do if a component changes unrelated to an @Input parameter? constructor(private dataService: DataService) {} ngOnInit() { this.dataService.updates$ .subscribe(newData => this.data = newData); // no update! } Angular Performance So zünden Sie den Turbo Change Detector

Slide 47

Slide 47 text

ChangeDetectorRef constructor(cdRef: ChangeDetectorRef) {} A reference to the ChangeDetector of your component - detectChanges() ✅ - markForCheck() - detach() - checkNoChanges() - reattach() Angular Performance So zünden Sie den Turbo Change Detector

Slide 48

Slide 48 text

markForCheck() Explicitly marks a component as dirty/changed (when using OnPush) Angular Performance So zünden Sie den Turbo Change Detector AppComponent CD NavComponent CD ContentComponent CD ListComponent CD DIRTY AppComponent CD NavComponent CD ContentComponent CD ListComponent CD OnPush

Slide 49

Slide 49 text

markForCheck() constructor(private dataService: DataService, private cdRef: ChangeDetectorRef) {} ngOnInit() { this.dataService.updates$.subscribe(newData => { this.data = newData; this.cdRef.markForCheck(); }); } Angular Performance So zünden Sie den Turbo Change Detector

Slide 50

Slide 50 text

Detaching Components changeDetector.detach(); changeDetector.reattach(); Angular Performance So zünden Sie den Turbo Change Detector AppComponent CD NavComponent CD ContentComponent CD ListComponent CD AppComponent CD NavComponent CD ContentComponent CD ListComponent CD ! View and model can get out of sync!

Slide 51

Slide 51 text

Local Change Detection constructor(cdRef: ChangeDetectorRef) { cdRef.detach(); // detaches this view from the CD tree // cdRef.detectChanges(); // detect this view & children // cdRef.reattach(); } Angular Performance So zünden Sie den Turbo Change Detector

Slide 52

Slide 52 text

Detaching components ng g c test Use in app.component.html // test.component.ts title = 'test'; constructor(public cdRef: ChangeDetectorRef) { cdRef.detach(); } // test.component.html {{ title }} Angular Performance So zünden Sie den Turbo Change Detector EX #4

Slide 53

Slide 53 text

Findings Reduce amount of change detection cycles - Disable Zone.js (not a good idea in most cases) - Coalesce CD cycles (might change behavior of existing apps) - Opt-out of NgZone (for operations that should not affect bindings) - Disable Zone.js patches (in case you can’t opt-out, e.g. 3rd party libs) - ChangeDetectionStrategy.OnPush (good default, but be careful) - Local change detection via ChangeDetectorRef (for the few components that do not have to respond to changes from outside) Angular Performance So zünden Sie den Turbo Change Detector

Slide 54

Slide 54 text

Runtime Performance Bundling Lazy Loading Preloading Strategies Server-Side Rendering Service Worker Angular Performance So zünden Sie den Turbo Agenda Change Detection Basics Zone.js & NgZone Change Detection Strategies Change Detector Async Pipe Load Time Performance

Slide 55

Slide 55 text

Overview Takes observables, promises or synchronous values {{ data$ | async }} Waits for the observable to emit/promise to resolve and then displays the value Angular Performance So zünden Sie den Turbo Async Pipe

Slide 56

Slide 56 text

Advantages For observables: - Async Pipe subscribes for you - Async Pipe takes care of unsubscribing from the observable - Async Pipe calls markForCheck for each update – perfect match for OnPush! https://github.com/angular/angular/blob/master/packages/common/src/pipes/async_pipe.ts Angular Performance So zünden Sie den Turbo Async Pipe

Slide 57

Slide 57 text

Simplifying OnPush constructor(private dataService: DataService, private cdRef: ChangeDetectorRef) {} ngOnInit() { this.dataService.updates$.subscribe(newData => { this.data = newData; this.cdRef.markForCheck(); }); } Angular Performance So zünden Sie den Turbo Async Pipe

Slide 58

Slide 58 text

Simplifying OnPush // component.ts data$: Observable; constructor(dataService: DataService) { this.data$ = this.dataService.updates$; } // component.html {{ data$ | async }} Angular Performance So zünden Sie den Turbo Async Pipe

Slide 59

Slide 59 text

ng g c async Use in AppComponent Make AsyncComponent OnPush // async.component.ts title$ = of('foo').pipe(delay(1000)); // async.component.html {{ title$ | async }} Angular Performance So zünden Sie den Turbo Async Pipe EX #5

Slide 60

Slide 60 text

- Reduce initial load (size & computation) - Reduce perceived loading time - Prevent downloading the same resource again Angular Performance So zünden Sie den Turbo Load Time Performance

Slide 61

Slide 61 text

Runtime Performance Bundling Lazy Loading Preloading Strategies Server-Side Rendering Service Worker Angular Performance So zünden Sie den Turbo Agenda Change Detection Basics Zone.js & NgZone Change Detection Strategies Change Detector Async Pipe Load Time Performance

Slide 62

Slide 62 text

The Problem Angular’s development directory structure is hard to • deploy • serve • cache • … Lots of files, lots of requests Angular and its dependencies are large in size, apps use only a fragment Bundling So zünden Sie den Turbo Angular Performance

Slide 63

Slide 63 text

The Problem Just-in-Time compilation (JiT) - Slow, client-side rendering - Compiler is 1.2 MB large in size - Template errors detected at runtime only - Potentially dangerous (injection attacks) Bundling So zünden Sie den Turbo Angular Performance

Slide 64

Slide 64 text

The Problem Goal: Angular app - with all components pre-compiled - combined in a single (or few) file(s) - without redundant/unused code - uglified, compressed Bundling So zünden Sie den Turbo Angular Performance

Slide 65

Slide 65 text

Angular Compilation Bundling Component @Component({ … }) class UserComponent { user = { name: 'Chris' }; } Template
hello {{ user.name }}
View Class var v = this.comp.user.name; So zünden Sie den Turbo Angular Performance

Slide 66

Slide 66 text

{{ title }}

Bundling So zünden Sie den Turbo Angular Performance

Slide 67

Slide 67 text

JiT Compilation Bundling Component @Component({ … }) class UserComponent { user = { name: 'Chris' }; } Template
hello {{ user.name }}
Server Client Component @Component({ … }) class UserComponent { user = { name: 'Chris' }; } Template
hello {{ user.name }}
View Class var v = this.comp.user.name; So zünden Sie den Turbo Angular Performance

Slide 68

Slide 68 text

AoT Compilation Bundling Component @Component({ … }) class UserComponent { user = { name: 'Chris' }; } Template
hello {{ user.name }}
Server Client Component @Component({ … }) class UserComponent { user = { name: 'Chris' }; } View Class var v = this.comp.user.name; Template
hello {{ user.name }}
View Class var v = this.comp.user.name; So zünden Sie den Turbo Angular Performance

Slide 69

Slide 69 text

Tree Shaking “A Tree Shaker walks the dependency graph, top to bottom, and shakes out unused code like dead needles in a Christmas tree.” Bundling So zünden Sie den Turbo Angular Performance

Slide 70

Slide 70 text

!function(){ var obj = { foo: function () { // Hi there! }, bar: function () { this.baz(); }, baz: function () { // stub } }; obj.foo(); }(); Tree Shaking Principle Bundling So zünden Sie den Turbo Angular Performance

Slide 71

Slide 71 text

Differential Loading ES5: function add(a,b){return a+b} ES 2015: add=(a,b)=>a+b ES 2015 introduced shorter syntax (smaller footprint/saves bandwidth) Detect the platform and only deliver files required for this platform Larger ES5 bundles are only delivered to legacy browsers Note: ES5 bundles are disabled unless targeting older browsers Angular Performance So zünden Sie den Turbo Bundling

Slide 72

Slide 72 text

Differential Loading // index.html </body></html> Angular Performance So zünden Sie den Turbo Bundling

Slide 73

Slide 73 text

Try some builds… ng build --aot false //no Tree Shaking, JiT ng build //no Tree Shaking, AoT ng build --prod // Tree Shaking, AoT Do not count Source Maps (*.js.map) and ES5 bundles (if any). Bundling So zünden Sie den Turbo Angular Performance EX #6

Slide 74

Slide 74 text

A Simple Demo App Dev build: 4.1 MB (ES 2015, without source maps) AoT build: 2.6 MB (ES 2015, without source maps) AoT+Tree Shaking: 274K (ES 2015, 83K gzipped) Bundling So zünden Sie den Turbo Angular Performance

Slide 75

Slide 75 text

A Simple Demo App JiT build: ~24018 ms AoT build: ~15530 ms AoT+Tree Shaking: ~20731 ms 2018 MacBook Pro, served locally a few test runs, results may & will vary Bundling So zünden Sie den Turbo Angular Performance

Slide 76

Slide 76 text

AoT Drawbacks Dynamic template compilation is discouraged in combination with AoT JitCompiler is unavailable - https://github.com/angular/angular/issues/15510 Bundling So zünden Sie den Turbo Angular Performance

Slide 77

Slide 77 text

Runtime Performance Bundling Lazy Loading Preloading Strategies Server-Side Rendering Service Worker Angular Performance So zünden Sie den Turbo Agenda Change Detection Basics Zone.js & NgZone Change Detection Strategies Change Detector Async Pipe Load Time Performance

Slide 78

Slide 78 text

Overview Angular router supports lazy loading components transparently Lazy loaded components are not delivered to/loaded by the client on boot, but on purpose Reduces load & perceived loading time Lazy Loading So zünden Sie den Turbo Angular Performance

Slide 79

Slide 79 text

Architecture Lazy Loading is module-based Module is resolved via a dynamic import: import('./feature.module').then(m => m.FeatureModule) Routing is delegated to the feature module called Lazy Loading So zünden Sie den Turbo Angular Performance

Slide 80

Slide 80 text

Overview const ROUTES: Routes = [{ path: 'admin', loadChildren: () => import('app/admin/admin.module') .then(a => a.AdminModule) }]; Lazy Loading So zünden Sie den Turbo Angular Performance

Slide 81

Slide 81 text

ng g m lazy --routing ng g c lazy/lazy Add a route for LazyComponent to lazy/lazy-routing.module.ts const routes: Routes = [{ path: '', component: LazyComponent }]; Configure app-routing.module.ts as follows: const routes: Routes = [{ path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(l => l.LazyModule) }]; Angular Performance So zünden Sie den Turbo Lazy Loading EX #7

Slide 82

Slide 82 text

Runtime Performance Bundling Lazy Loading Preloading Strategies Server-Side Rendering Service Worker Angular Performance So zünden Sie den Turbo Agenda Change Detection Basics Zone.js & NgZone Change Detection Strategies Change Detector Async Pipe Load Time Performance

Slide 83

Slide 83 text

Configuring Lazy Loading NoPreloading - does not preload any route by default - advantage: low size footprint - disadvantage: takes some time after clicking a link to the lazy-loaded module, not offline capable PreloadAllModules - automatically preloads all modules after the application has launched (still better loading time!) - advantage: lazy-loaded modules now load instant (also on the first click), offline capable - disadvantage: higher footprint Angular Performance So zünden Sie den Turbo Preloading Strategies

Slide 84

Slide 84 text

Configuring Lazy Loading @NgModule({ imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules, })], exports: [RouterModule] }) export class AppRoutingModule { } Angular Performance So zünden Sie den Turbo Preloading Strategies

Slide 85

Slide 85 text

Custom Strategy It’s also possible to provide a custom strategy - when modules belong to each other - it’s expected that the user will access a certain module next (e.g. checkout after cart module) Developer can decide which modules should be preloaded on a navigation event Developer gets access to the modules which have not been preloaded yet Angular Performance So zünden Sie den Turbo Preloading Strategies

Slide 86

Slide 86 text

Custom Strategy preload(route: Route, fn: () => Observable): Observable { // decide based on route (or other external information) // call fn to preload the module // otherwise, return of(null) } https://github.com/angular/angular/blob/8.2.10/packages/router/src/router_preloader.ts#L30-L58 Angular Performance So zünden Sie den Turbo Preloading Strategies

Slide 87

Slide 87 text

Custom Strategy ng g s myPreloadingStrategy (automatically adds @Injectable which is great for this demo, but typically you would not call it a service) // myPreloadingStrategy.service.ts export class MyPreloadingStrategyService implements PreloadingStrategy preload(route: Route, fn: () => Observable): Observable { console.log(route); return fn(); } // app-routing.module.ts RouterModule.forRoot(routes, { preloadingStrategy: MyPreloadingStrategyService }) Angular Performance So zünden Sie den Turbo Preloading Strategies EX #8

Slide 88

Slide 88 text

Runtime Performance Bundling Lazy Loading Preloading Strategies Server-Side Rendering Service Worker Angular Performance So zünden Sie den Turbo Agenda Change Detection Basics Zone.js & NgZone Change Detection Strategies Change Detector Async Pipe Load Time Performance

Slide 89

Slide 89 text

Angular Universal Renders Angular content on a server (i.e. not in a browser environment) Provided by the Angular team Open Source https://github.com/angular/universal Has CLI integration Server-Side Rendering So zünden Sie den Turbo Angular Performance

Slide 90

Slide 90 text

Angular App Application Layer Rendering Layer Web Worker Server Browser NativeScript … Platform Server-Side Rendering So zünden Sie den Turbo Angular Performance

Slide 91

Slide 91 text

Principle Pre-render the website using the same sources that are served Once Angular kicks in, the view is replaced with the client-rendered one Supports Node.js (Express), ASP.NET Core, Hapi.js & plain sockets JiT and AoT support (AoT strictly recommended for production) Server-Side Rendering So zünden Sie den Turbo Angular Performance

Slide 92

Slide 92 text

Principle Server-Side Rendering Component @Component({ … }) class UserComponent { user = { name: 'Chris' }; } Template
hello {{ user.name }}
Server Client Component @Component({ … }) class UserComponent { user = { name: 'Chris' }; } View Class var v = this.comp.user.name; Template
hello {{ user.name }}
View Class var v = this.comp.user.name; index.html … So zünden Sie den Turbo Angular Performance

Slide 93

Slide 93 text

Purpose Search Engine Optimization Preview Links (Social Media) Graceful Degradation Reduce Perceived Loading Time/Quick First Contentful Paint (FCP) Improve Performance for Mobile/Low-Powered Devices Server-Side Rendering So zünden Sie den Turbo Angular Performance

Slide 94

Slide 94 text

Server Rendering Asset Downloads Client Init Client Data Paint The Web App Gap Server-Side Rendering So zünden Sie den Turbo Angular Performance

Slide 95

Slide 95 text

Preboot Filling the Web App Gap Records interactions of the user on the server-rendered part Replays the interaction once Angular kicks in on the client side Provided by the Angular team Open source https://github.com/angular/preboot Server-Side Rendering So zünden Sie den Turbo Angular Performance

Slide 96

Slide 96 text

Server Rendering Asset Downloads Client Init Client Data Paint Preboot & The Web App Gap Angular Performance So zünden Sie den Turbo Server-Side Rendering Record Replay

Slide 97

Slide 97 text

Preboot & Angular @NgModule({ declarations: [AppComponent], imports: [ BrowserModule.withServerTransition({ appId: 'foo' }), PrebootModule.withConfig({ appRoot: 'app-root' }) ], bootstrap: [AppComponent] }) export class AppModule { } Angular Performance So zünden Sie den Turbo Server-Side Rendering

Slide 98

Slide 98 text

ng add @nguniversal/express-engine --clientProject perf-demo npm run build:ssr npm run serve:ssr http://localhost:4000 Check Network tab in DevTools Angular Performance So zünden Sie den Turbo Server-Side Rendering EX #9

Slide 99

Slide 99 text

Runtime Performance Bundling Lazy Loading Preloading Strategies Server-Side Rendering Service Worker Angular Performance So zünden Sie den Turbo Agenda Change Detection Basics Zone.js & NgZone Change Detection Strategies Change Detector Async Pipe Load Time Performance

Slide 100

Slide 100 text

Idea: Never load the same resource twice Download resources once and store them in a local cache The next time the user wants to open the application, load the contents from there Makes your application sources offline-capable Significantly improves loading time Angular Performance So zünden Sie den Turbo Service Worker

Slide 101

Slide 101 text

Key Technology Service Worker Service Worker Internet Website HTML/JS Cache fetch So zünden Sie den Turbo Angular Performance

Slide 102

Slide 102 text

@angular/service-worker Service Worker implementation provided by the Angular team Features - Caching - Offline Availability - Push Notifications Service Worker is generated by the CLI (prod builds only) Service Worker So zünden Sie den Turbo Angular Performance

Slide 103

Slide 103 text

Features ng add @angular/pwa ng build --prod cd dist/browser npx lite-server Service Worker So zünden Sie den Turbo Angular Performance EX #10

Slide 104

Slide 104 text

Runtime Performance Don’t over-optimize Reduce duration of a change detection cycle - Reduce amount of bindings - Avoid binding to (computationally intensive) getters or functions Reduce amount of change detection cycles - Disable zone or coalesce events - NgZone - Zone.js patches - ChangeDetectorRef - ChangeDetectionStrategy Angular Performance So zünden Sie den Turbo Summary

Slide 105

Slide 105 text

Thank you for your kind attention! Christian Liebel @christianliebel [email protected]