Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Datenbindung und Performance in Angular 2

905 views

Published on

Folien zu Vortrag auf den Angular 2 Days im Oktober 2016 in Berlin.

Published in: Internet
  • Be the first to comment

  • Be the first to like this

Datenbindung und Performance in Angular 2

  1. 1. 20.10.2016 1 ManfredSteyer Über mich … • Manfred Steyer • SOFTWAREarchitekt.at • Trainer & Consultant • GDE & MVP • Focus: Angular 2 Page  3 ManfredSteyer
  2. 2. 20.10.2016 2 Ziele • Wie funktioniert die Datenbindung in Angular 2? • Wie kann man die Performance für Datenbindung verbessern? • Immutables • Observables Nicht-Ziele • Allgemeine Einführung in Angular 2
  3. 3. 20.10.2016 3 Didaktik • 1. Abschnitt • Präsentation • Live-Coding • 2. Abschnitt • Übung mit Übungsblatt und Starterkit Inhalt • Überblick zur Datenbindung in Angular 2 • Datenbindung hinter den Kulissen • Two-Way-Binding • Überblick zu Immutables • Performancetuning mit Immutables • Überblick zu Observables • Performancetuning mit Observables • Übung • Bonus: Ausblick auf AOT-Kompilierung
  4. 4. 20.10.2016 4 Benchmark Überblick zur Datenbindung in Angular 2
  5. 5. 20.10.2016 5 Angular-2-Anwendungen sind Komponenten Page  12 @Component({ selector: 'flight-search', templateUrl: 'flight-search.html' }) export class FlightSearchComponent { from: string; to: string; flights: Array<Flight>; constructor(http: Http) { } search() { [...] } select(flight: Flight) { [...] } } Page  13 <input [(ngModel)]="from"> <input [(ngModel)]="to"> <button [disabled]="!from || !to" (click)="search()"> Search </button> <table> <tr *ngFor="let f of flights"> <td>{{f.id}}</td> <td>{{f.date}}</td> <td>{{f.from}}</td> <td>{{f.to}}</td> </tr> </table> Template
  6. 6. 20.10.2016 6 Hinter den Kulissen Page  14 Architektur-Ziele von Angular 2 Page  15 Performance Komponenten Vorhersagbarkeit
  7. 7. 20.10.2016 7 Data-Binding in AngularJS 1.x Page  16 Model Model Directive Komponentne-Baum in Angular 2 Page  17 Komponente für gesamte App Komponente (z. B. list) Komponente (z. B. list-item) Komponente (z. B. list-item)
  8. 8. 20.10.2016 8 Regeln für Property Bindings • Komponente hängt nur von Daten des Parents ab • Komponente hängt nie von Daten der Kinder ab • Abhängigkeits-Graph is ein Baum • Angular benötigt nur eine einzige Iteration („digest“) zum Abgleich des Baumes Page  18 Property-Binding Page  19 model item item {{ item.title }} {{ item.title }} [http://victorsavkin.com/post/110170125256/change-detection-in-angular-2]
  9. 9. 20.10.2016 9 Event-Bindings (One-Way, Bottom/Up) Page  20 {{ item.title }} {{ item.title }} Event-Handler Event-Handler Event-Bindings (One-Way, Bottom/Up) • Kein Digest nötig • Event-Handler == Callbacks • Aber: Events können Anwendungszustand verändern  Digest um Property-Bindings zu aktualisieren Page  21
  10. 10. 20.10.2016 10 Property- und Event-Bindings Page  22 Property-Bindings ausführen Event-Handler warden ausgeführt Ereignis tritt ein Anwendung ist bereit! Alle Handler ausgeführt Properties gebunden Bindings definieren Page  23
  11. 11. 20.10.2016 11 View Page  24 <button (click)="search()" [disabled]="!from || !to">Search</button> <table> <tr *ngFor="let flight of flights"> <td>{{flight.id}}</td> <td>{{flight.date}}</td> <td>{{flight.from}}</td> <td>{{flight.to}}</td> <td><a href="#" (click)="selectFlight(flight)">Select</a></td> </tr> </table> <td [text-content]="flight.id"></td> Recap • Property-Binding: One-Way; Top/Down • Event-Binding: One-Way; Bottom/Up • Two-Way-Binding? • Two-Way = Property-Binding + Event-Binding Page  25
  12. 12. 20.10.2016 12 Property- und Event-Bindings kombinieren Page  26 <input [ngModel]="from" (ngModelChange)="updateFrom($event)"> updateFrom(newValue) { this.from = newValue; } Property- und Event-Bindings kombinieren Page  27 <input [ngModel]="from" (ngModelChange)="from = $event">
  13. 13. 20.10.2016 13 Syntax-Zucker für Two-Way-Binding Page  28 <input [(ngModel)]="from"> Vorteile • Performance • Events: Flexibilität • Syntaxzucker: Einfache Nutzung Page  29
  14. 14. 20.10.2016 14 DEMO: Two-Way-Binding Page  30 Beispiel: flight-card Page  31
  15. 15. 20.10.2016 15 Einsatz der flight-card Page  32 <div *ngFor="let f of flights"> <flight-card [item]="f" [selectedItem]="selectedFlight" (selectedItemChange)="selectedFlight = $event"> </flight-card> </div> flight-card Page  33 flug-card item selectedItem > > > selectedItemChange flug selectedFlug
  16. 16. 20.10.2016 16 Beispiel: flight-card @Component({ selector: 'flight-card', templateUrl: './flight-card.component.html' }) export class FlightCard { @Input() item; @Input() selectedItem; @Output() selectedItemChange = new EventEmitter(); select() { this.selectedItemChange.emit(this.item); } } Template <div style="padding:20px;" [ngStyle]="{'background-color': (selectedItem == item) ? 'orange' : 'lightsteelblue' }" > <h2>{{item.from}} - {{item.to}}</h2> <p>Flugnr. #{{item.id}}</p> <p>Datum: {{item.date}}</p> <p> <button class="btn btn-default" (click)="select()"> Select </button> </p> </div>
  17. 17. 20.10.2016 17 DEMO Performance-Tuning mit Immutables
  18. 18. 20.10.2016 18 Angular traversiert standardmäßig den gesamten Komponenten-Baum flights flight flight {{ flight.id }} {{ flight.id }} FlightSearch Card Card Immutables • Unveränderbare Objekte • Wenn sich repräsentierte Daten ändern: Neues Objekt erzeugen • Man kann einfach herausfinden, ob sich etwas geändert hat • oldObject == newObject • Mit oder ohne Bibliotheken möglich (wie immutable.js)
  19. 19. 20.10.2016 19 Beispiel const ONE_MINUTE = 1000 * 60; let oldFlights = this.flights; let oldFlight = oldFlights[0]; // Flight to change! let oldFlightDate = new Date(oldFlight.date); // Date to change Änderung ohne Immutables date.setTime(date.getTime() + ONE_MINUTE * 15); this.flights[0].date = date.toISOString();
  20. 20. 20.10.2016 20 Änderung mit Immutables let newFlightDate = new Date(oldFlightDate.getTime() + ONE_MINUTE * 15); let newFlight = { id: oldFlight.id, from: oldFlight.from, to: oldFlight.to, date: newFlightDate.toISOString() }; let newFlights = [ newFlight, ...oldFlights.slice(1, this.flights.length) ]; this.flights = newFlights; Auf Änderungen prüfen console.debug("Array: " + (oldFlights == newFlights)); // false console.debug("#0: " + (oldFlights[0] == newFlights[0])); // false console.debug("#1: " + (oldFlights[1] == newFlights[1])); // true
  21. 21. 20.10.2016 21 Immutables und Angular 2 • Annahme: Jedes @Input() einer Komponente ist immutable • Angular kann einfach prüfen, ob sich eingehende Daten einer Komponente ändern • Nur wenn das der Fall ist, müssen Komponente und deren Kind-Komponenten betrachtetet werden Immutables und Angular flights flight flight {{ flight.id }} {{ flight.id }} FlightSearch Card Card Änderung
  22. 22. 20.10.2016 22 Optimierung aktivieren @Component({ […] changeDetection: ChangeDetectionStrategy.OnPush }) export class FlightCard { […] @Input flight; } DEMO
  23. 23. 20.10.2016 23 Weitere Vorteile von Immutables • Vereinfacht Nachvollziehbarkeit und Testing -> Kein Zustand • Vereinfacht Undo/Redo Observables
  24. 24. 20.10.2016 24 Was sind Observables? • Repräsentieren asynchrone Daten, die im Verlauf der Zeit veröffentlicht werden Observer „Senke“ Observable „Quelle“ Operator (z. B. map)
  25. 25. 20.10.2016 25 Observable Observable .subscribe( (result) => { … }, (error) => { … }, () => { … } ); Observer Beispiel this .http .get("http://www.angular.at/api/...") .map(resp => resp.json()) .subscribe( (flights) => { … }, (err) => { console.error(err); } );
  26. 26. 20.10.2016 26 Eigenes Observable var observable = Observable.create((sender) => { sender.next(4711); sender.next(815); //sender.error("err!"); sender.complete(); }); Asynchron, Ereignis-gesteuert var subscription = observable.subscribe(…); subscription.unsubscribe(); return () => { console.debug('Bye bye'); }; Cold vs. Hot Observables Page  55 Cold • Standard • Punkt zu Punkt • Pro Empfänger ein Sender • Sender startet erst bei Anmeldung Hot • Punkt zu Multipunkt • Sender startet auch ohne Anmeldungen
  27. 27. 20.10.2016 27 Hot Observable Page  56 var o = Observable.create((observer) => { observer.next(42); observer.error("err!"); }).publish().connect(); Subjects Subject .subscribe( (result) => { … }, (error) => { … }, () => { … } ); Observer Daten/ Benachrichtigung von außen
  28. 28. 20.10.2016 28 Subjects Page  58 Subject Hot & verteilt empfangene Daten BehaviorSubject Speichert letzten Wert ReplaySubject Speichert mehrere Werte Performanceoptimierung mit Observables
  29. 29. 20.10.2016 29 Performance und Observables • Observable benachrichtigt über Datenänderungen • Datenbindung wird bei Benachrichtigung aktiv • Aktivierung: OnPush Observables mit OnPush Page  61 flights flight$ flight$ {{ flight$.id }} {{ flight$.id }} FlightSearch Card Card Änderung
  30. 30. 20.10.2016 30 Observables mit OnPush Page  62 flights$ flight flight {{ flight.id }} {{ flight.id }} FlightSearch Card Änderung Card Observable binden <flight-card [item]="flight | async" […]> </flight-card>
  31. 31. 20.10.2016 31 DEMO Nicht „Alles-oder-Nichts“ • Optimierungen mit Immutables und Observables funktionieren nicht nach dem „Alles-oder-Nichts“-Prinzip • Sie können bei Bedarf genutzt werden
  32. 32. 20.10.2016 32 DEMO Fazit • Property-Bindings: Top/Down, One-Way • Event-Bindings: Bottom/Up, One-Way • 2-Way-Bindings: Property-Binding + Event-Binding • Architektur: „Fast by default“ • Wer mehr Performance benötigt: Immutables und Observables
  33. 33. 20.10.2016 33 Kontakt [mail] manfred.steyer@SOFTWAREarchitekt.at [web] SOFTWAREarchitekt.at [twitter] ManfredSteyer Bonus: AOT-Kompilierung
  34. 34. 20.10.2016 34 Zusätzliche Performance HTML Template JavaScript Template Compiler input['value'] = flight['date'] input.value = flight.date; Ansätze für das Kompilieren von Templates • JIT: Just im Time, zur Laufzeit • AOT: Ahead of Time, beim Build
  35. 35. 20.10.2016 35 Vorteile von AOT • Bessere Startup-Performance • Kleinere Bundles: Compiler für JIT muss nicht ausgeliefert werden • Bessere statische Analysierbarkeit des Programmcodes HTML TypeScript TypeScript Angular 2 Tree Shaking
  36. 36. 20.10.2016 36 Installation des AOT-Compilers (ngc) • npm install @angular/compiler-cli --save-dev • npm install typescript@2.0.2 --save-dev • npm install @angular/platform-server --save Page  78 tsconfig.aot.json • module: ES2015 • Target: ES2015 Page  79 "angularCompilerOptions": { "genDir": "aot", "skipMetadataEmit" : true }
  37. 37. 20.10.2016 37 webpack2 • UglifyJsPlugin • LoaderOptionsPlugin • --optimize-minimize Page  80 Kompilieren • ngc -p tsconfig.aot.json Page  81
  38. 38. 20.10.2016 38 Bootstrapping Page  82 import { platformBrowser } from '@angular/platform-browser'; import { AppModuleNgFactory } from './app.module.ngfactory'; platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); DEMO
  39. 39. 20.10.2016 39 Fazit • Hohes Potential (Performance, Bundle-Größe, Tree-Shaking) • Sehr junges Feature • Tooling entsteht gerade (z. B. Integration in WebPack) • Wird wohl erst ab Version 2.1 „runde Sache“ Kontakt [mail] manfred.steyer@SOFTWAREarchitekt.at [web] SOFTWAREarchitekt.at [twitter] ManfredSteyer

×