Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Performance for Angular - New Possibilities and Proven Classics @AngularDays in Berlin, Oct 2018

Performance for Angular - New Possibilities and Proven Classics @AngularDays in Berlin, Oct 2018

15934fa2aa7b2ce21f091e9b7cffa856?s=128

Manfred Steyer
PRO

October 11, 2018
Tweet

Transcript

  1. @BASTAcon & @ManfredSteyer Performance for Angular New Possibilities and Proven

    Classics Manfred Steyer SOFTWAREarchitekt.at ManfredSteyer
  2. @BASTAcon & @ManfredSteyer About me… • Manfred Steyer • SOFTWAREarchitekt.at

    • Angular Trainings and Consultancy • Google Developer Expert (GDE) Page ▪ 3 Manfred Steyer Public: Vienna, München, Zürich In-House: everywhere http://softwarearchitekt.at/workshops
  3. @BASTAcon & @ManfredSteyer Turbo Button

  4. @BASTAcon & @ManfredSteyer Quick Wins Bundling Minification enableProdMode()

  5. @BASTAcon & @ManfredSteyer Contents • Lazy Loading • Performance for

    Data Binding with OnPush • AOT and Tree Shaking • New and upcoming features • Caching with Service Worker • Serverside Rendering
  6. @BASTAcon & @ManfredSteyer Lazy Loading

  7. @BASTAcon & @ManfredSteyer Module Structure Page ▪ 8 AppModule …

    … … SharedModule Root Module Feature Modules Shared Module
  8. @BASTAcon & @ManfredSteyer Lazy Loading Page ▪ 9 AppModule …

    … … SharedModule Root Module Feature Modules Shared Module
  9. @BASTAcon & @ManfredSteyer Root Module with Lazy Loading Page ▪

    10 const APP_ROUTE_CONFIG: Routes = [ { path: 'home', component: HomeComponent }, { path: 'flights', loadChildren: './[…]flight-booking.module#FlightBookingModule' } ];
  10. @BASTAcon & @ManfredSteyer Routes for "lazy" Module Page ▪ 11

    const FLIGHT_ROUTES = [ { path: '', component: FlightBookingComponent, […] }, […] }
  11. @BASTAcon & @ManfredSteyer Routes for "lazy" Module Page ▪ 12

    const FLIGHT_ROUTES = [ { path: 'subroute', component: FlightBookingComponent, […] }, […] } flight-booking/subroute Triggers Lazy Loading w/ loadChildren
  12. @BASTAcon & @ManfredSteyer DEMO

  13. @BASTAcon & @ManfredSteyer Preloading

  14. @BASTAcon & @ManfredSteyer Idea • Module that might be needed

    later are loaded after the application started • When module is needed it is available immediately Page ▪ 17
  15. @BASTAcon & @ManfredSteyer Activate Preloading Page ▪ 18 … imports:

    [ […] RouterModule.forRoot( ROUTE_CONFIG, { preloadingStrategy: PreloadAllModules }); ] …
  16. @BASTAcon & @ManfredSteyer DEMO

  17. @BASTAcon & @ManfredSteyer Performance- Tuning with OnPush

  18. @BASTAcon & @ManfredSteyer DEMO

  19. @BASTAcon & @ManfredSteyer OnPush flights flight flight {{ flight.id }}

    {{ flight.id }} FlightSearch Card Card Angular just checks when “notified”
  20. @BASTAcon & @ManfredSteyer "Notify" about change? • Change bound data

    (@Input) • OnPush: Angular just compares the object reference! • e. g. oldFlight === newFlight • Raise Event within the component • Notify a bound observable • observable$ | async • Trigger it manually • Don't do this at home ;-) • At least: Try to avoid this
  21. @BASTAcon & @ManfredSteyer Activate OnPush @Component({ […] changeDetection: ChangeDetectionStrategy.OnPush })

    export class FlightCard { […] @Input() flight; }
  22. @BASTAcon & @ManfredSteyer DEMO

  23. @BASTAcon & @ManfredSteyer Ahead of Time (AOT) Compilation

  24. @BASTAcon & @ManfredSteyer Angular Compiler HTML Template JavaScript Template Compiler

  25. @BASTAcon & @ManfredSteyer Approaches • JIT: Just in Time, at

    runtime • AOT: Ahead of Time, during build
  26. @BASTAcon & @ManfredSteyer Advantages of AOT • Better Startup-Performance •

    Smaller Bundles: You don't need to include the compiler! • Tools can easier analyse the code • Remove unneeded parts of frameworks • Tree Shaking
  27. @BASTAcon & @ManfredSteyer Angular CLI • ng build --prod •

    @ngtools/webpack with AngularCompilerPlugin • Can be used without CLI too
  28. @BASTAcon & @ManfredSteyer DEMO

  29. @BASTAcon & @ManfredSteyer Bundles without AOT and Tree Shaking JIT

    Compiler
  30. @BASTAcon & @ManfredSteyer AOT is stricter than JIT !

  31. @BASTAcon & @ManfredSteyer Solutions Angular Language Service • Plugins for

    IDEs AOT for debugging • Possible since Angular 5 • Incremental AOT • Fast after 1st recompilation • ng serve --aot • Give it a try!
  32. @BASTAcon & @ManfredSteyer Angular Build Optimizer makes code more treeshakable

    (default since CLI 1.5)
  33. @BASTAcon & @ManfredSteyer Treeshakable Providers >= Angular 6

  34. @BASTAcon & @ManfredSteyer Classical Providers @NgModule({ [...] providers: [ FlightService

    ], [...] }) export class Module { }
  35. @BASTAcon & @ManfredSteyer

  36. @BASTAcon & @ManfredSteyer Service Page ▪ 42 @Injectable({ providedIn: 'root'

    }) export class FlugService { […] } Globaler Scope
  37. @BASTAcon & @ManfredSteyer Alternative Page ▪ 43 @Injectable({ providedIn: LazyApiModule

    }) export class FlugService { […] } Macht nur mit Lazy Loading sinn!! Service wird mit lazy Module mitgeladen
  38. @BASTAcon & @ManfredSteyer ngIvy Outlook

  39. @BASTAcon & @ManfredSteyer Further improvements in upcoming versions New Compiler/

    View Engine More treeshakable Code No Breaking Changes Experimental with Angular 6
  40. @BASTAcon & @ManfredSteyer

  41. @BASTAcon & @ManfredSteyer

  42. @BASTAcon & @ManfredSteyer Beyond Tree Shaking

  43. @BASTAcon & @ManfredSteyer Google Closure Compiler Aggressive Optimizations E2E-Test necessary

    Expert Tool Difficult to configure! Office 365 Google Docs, etc.
  44. @BASTAcon & @ManfredSteyer Sample class Stuff { static stuff(data: string)

    { console.log('stuff: ' + data); } } function stuff(data: string) { Stuff.stuff(data); } stuff('Hallo Welt!'); console.log("stuff: Hallo Welt!");
  45. @BASTAcon & @ManfredSteyer RxJS is huge

  46. @BASTAcon & @ManfredSteyer RxJS • We don't need every operator/

    method • But: Methods are not tree-shakable for CLI/ webpack and others • Solution: Just import methods you need • Imports are patching Observable
  47. @BASTAcon & @ManfredSteyer Import Operators import 'rxjs/add/operator/map'; // Patch Observable

    --> add map import 'rxjs/add/operator/filter'; this.http.get<Flight>(url) .filter(f => f.price < 300) .map(f => toFlightOffer(f)) .subscribe(…); Not treeshakable!
  48. @BASTAcon & @ManfredSteyer Better Alternative: Pipeable Operators this.http.get<Flight>(url) .pipe( filter(f

    => f.price < 300), map(f => toFlightOffer(f)) ) .subscribe(…); import { map, filter } 'rxjs/operators';
  49. @BASTAcon & @ManfredSteyer Removing Whitespaces

  50. @BASTAcon & @ManfredSteyer Removing Whitespaces <p> Hello</p> <p>World! </p>

  51. @BASTAcon & @ManfredSteyer Removing Whitespaces <p> Hello</p> <p>World! </p> \n

    //Pseudo Code createNode('p', ' Hello World'); createNode('TEXT-NODE', '\n'); createNode('p', 'World!'); Template Compiler
  52. @BASTAcon & @ManfredSteyer Removing Whitespaces <p> Hello</p> <p>World! </p> \n

    //Pseudo Code createNode('p', ' Hello World'); createNode('TEXT-NODE', '\n'); createNode('p', 'World!'); Template Compiler
  53. @BASTAcon & @ManfredSteyer Removing Whitespaces @Component({ selector: 'flight-card', templateUrl: './flight-card.component.html',

    styleUrls: ['./flight-card.component.css'], preserveWhitespaces: false }) export class FlightCardComponent { […] }
  54. @BASTAcon & @ManfredSteyer Switching it on globally in tsconfig.app.json […]

    "angularCompilerOptions": { "preserveWhitespaces": false } […]
  55. @BASTAcon & @ManfredSteyer Caching with Service Worker

  56. @BASTAcon & @ManfredSteyer Service Worker Browser Service-Worker Anfrage Antwort Cache

    Same Origin Policy You control this!
  57. @BASTAcon & @ManfredSteyer Two possible abstractions for Service Worker @angular/service-worker

  58. @BASTAcon & @ManfredSteyer ng add @angular/pwa

  59. @BASTAcon & @ManfredSteyer DEMO

  60. @BASTAcon & @ManfredSteyer Server Side Rendering

  61. @BASTAcon & @ManfredSteyer Why Server Side Rendering? Prerender 1st Page

    Start up performance Consumer Apps
  62. @BASTAcon & @ManfredSteyer renderModuleFactory […] renderModuleFactory(moduleFactory, { document: indexFileContentsAsString, url:

    options.req.url }) .then(htmlString => { […] }); […] Available since Angular 4.0
  63. @BASTAcon & @ManfredSteyer

  64. @BASTAcon & @ManfredSteyer Challenges Other conditions Separate Services for Server

    and Client-Seite Renderer abstracts DOM 3rd parts libs Angular 5: Server Side DOM Simulation (partly)
  65. @BASTAcon & @ManfredSteyer Conclusion Quick Wins Lazy Loading and Preloading

    OnPush w/ Immutables and Observables AOT and Tree Shaking Pipeable Rx-Operators Server Side Rendering Lean back: The ng team takes care!
  66. @BASTAcon & @ManfredSteyer More about this in my Medium Account

    • Configuration Details, Samples, Videos etc. • https://medium.com/@ManfredSteyer/angular-performance-tuning- article-series-6e3c33707b25
  67. @BASTAcon & @ManfredSteyer Contact and Downloads [mail] manfred.steyer@SOFTWAREarchitekt.at [web] SOFTWAREarchitekt.at

    [twitter] ManfredSteyer d http://softwarearchitekt.at/workshops Slides & Examples