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.
Small computers, big performance:
Optimize your Angular
Speakers
David Barreto
Solutions Architect @ Rangle.io
Blog: david-barreto.com
Andrew Smith
Solutions Architect @ Rangle.io
Agenda
1. Ahead of Time Compilation
2. Lazy Loading
3. Change Detection
4. Memory Leaks
5. Server Side Rendering
Rangle Academy
Goal and Structure:
Program to share knowledge within the company
It follows a "workshop" structure
Usually...
About the Demo App
Characteristics:
Built using Angular 2.4.1
Uses Angular CLI beta-26
Redux store with ngrx
Tachyons for ...
Ahead of Time Compilation (AoT)
Compilation Modes
Just in Time Compilation (JiT):
Compilation performed in the browser at run time
Bigger bundle size (inc...
JiT vs AoT in Demo App (Prod + Gzip)
CSS files are included in the "other js files"
File Size (JiT) Size (AoT)
main.bundle...
Boot Time Comparison
Event Time (JiT) Time (AoT)
DOM Content Loaded 5.44 s 3.25 s
Load 5.46 s 3.27 s
FMP 5.49 s 3.30 s
DOM...
Lazy Loading
What is Lazy Loading?
Ability to load modules on demand => Useful to reduce the app startup time
(Compare branches no-lazy...
Bundle Sizes Comparison (Prod + AoT)
File Size (No LL) Size (LL)
main.bundle.js 23.9 KB 17.4 KB
vendor.bundle.js 158 KB 15...
Boot Time Comparison (Prod + AoT)
Event Time (No LL) Time (LL)
DOM Content Loaded 3.25 s 3.11 s
Load 3.27 s 3.25 s
FMP 3.3...
Preloading
(Compare branches normal-lazy-loading vs master )
Enable Preloading
Define the property preloadingStrategy in the root module routing
import { PreloadAllModules } from '@an...
Change Detection
What's Change Detection (CD)?
It's a mechanism to keep our "models" in sync with our "views"
Change detection is fired whe...
Change Detection Strategy: OnPush
Angular offers 2 strategies:
Default: Check the entire component when CD is fired
OnPush:...
Example: The Component Tree
Default Change Detection
OnPush Change Detection
Summary
What to do?
Apply the OnPush change detection on every component*
Never mutate an object or array, always create a...
Memory Leaks
What's Memory Leak?
The increase of memory usage over time
What Causes Memory Leaks in Angular?
Main Source => Subscriptions to observables never closed
@Injectable()
export class W...
Manually Closing Connections
Before the element is destroyed, close the connection
@Component({
selector: 'rio-workshop-li...
The async Pipe
It closes the connection automatically when the component is destroyed
@Component({
selector: 'rio-workshop...
The Http Service
Every method of the http services ( get , post , etc.) returns an observable
Those observables emit only ...
Emit a Limited Number of Values
RxJs provides operators to close the connection automatically
Examples: first() and take(n...
Server Side Rendering
Angular Universal
Provides the ability to pre-render your application on the server
Much faster time to first paint
Enable...
What's Included
Suite of polyfills for the server
Server rendering layer
Preboot - replays your user's interactions after ...
Boot Time Comparison (Client vs Server)
Both environments include previous AoT and Lazy Loading enhancements
Event Time (C...
Universal Caveats
Cannot directly access the DOM
constructor(element: ElementRef, renderer: Renderer) {
renderer.setElemen...
Summary
Performance Changes
Event JiT AoT Lazy Loading SSR
DOM Content Loaded 5.44 s 3.25 s 3.11 s 411 ms
Load 5.46 s 3.27 s 3.25 ...
Thank You
Slides: https://github.com/rangle/angular-performance-meetup
Angular Optimization Web Performance Meetup
Angular Optimization Web Performance Meetup
Upcoming SlideShare
Loading in …5
×

Angular Optimization Web Performance Meetup

152 views

Published on

Slides for the Web Performance Meetup

Published in: Software
  • Be the first to comment

  • Be the first to like this

Angular Optimization Web Performance Meetup

  1. 1. Small computers, big performance: Optimize your Angular
  2. 2. Speakers David Barreto Solutions Architect @ Rangle.io Blog: david-barreto.com Andrew Smith Solutions Architect @ Rangle.io
  3. 3. Agenda 1. Ahead of Time Compilation 2. Lazy Loading 3. Change Detection 4. Memory Leaks 5. Server Side Rendering
  4. 4. Rangle Academy Goal and Structure: Program to share knowledge within the company It follows a "workshop" structure Usually 2 hours long Covers hard and soft skills Some workshops available: Webpack React React Native Google Analytics Unit Testing Introduction to Payment Gateways Continuous Delivery to Production Conflict Management
  5. 5. About the Demo App Characteristics: Built using Angular 2.4.1 Uses Angular CLI beta-26 Redux store with ngrx Tachyons for CSS Server side rendering with Angular Universal All the numbers shown are based on: Low end device (5x CPU slowdown) Good 3G connection (Latency: 40ms, DL: 1.5 Mbps, UL: 750 Kbps)
  6. 6. Ahead of Time Compilation (AoT)
  7. 7. Compilation Modes Just in Time Compilation (JiT): Compilation performed in the browser at run time Bigger bundle size (includes the compiler) Takes longer to boot the app $ ng serve --prod Ahead of Time Compilation (AoT): Compilation performed in the server at build time Smaller bundle size (doesn't include the compiler) The app boots faster $ ng serve --prod --aot
  8. 8. JiT vs AoT in Demo App (Prod + Gzip) CSS files are included in the "other js files" File Size (JiT) Size (AoT) main.bundle.js 6.4 KB 23.9 KB vendor.bundle.js 255 KB 158 KB other js files 48.7 KB 49.6 KB Total Download 306 KB 231.5 KB AoT goals (from the ):docs Faster rendering => Components already compiled Fewer async request => Inline external HTML and CSS Smaller bundle size => No compiler shipped Detect template errors => Because they can Better security => Prevents script injection attack
  9. 9. Boot Time Comparison Event Time (JiT) Time (AoT) DOM Content Loaded 5.44 s 3.25 s Load 5.46 s 3.27 s FMP 5.49 s 3.30 s DOM Content Loaded: The browser has finished parsing the DOM jQuery nostalgia => $(document).ready() Load: All the assets has been downloaded First Meaningful Paint (FMP): When the user is able to see the app "live" for the first time (Show browser profile for both modes)
  10. 10. Lazy Loading
  11. 11. What is Lazy Loading? Ability to load modules on demand => Useful to reduce the app startup time (Compare branches no-lazy-loading vs normal-lazy-loading )
  12. 12. Bundle Sizes Comparison (Prod + AoT) File Size (No LL) Size (LL) main.bundle.js 23.9 KB 17.4 KB vendor.bundle.js 158 KB 158 KB other js files 49.6 KB 49.6 KB Initial Download 231.5 KB 225 KB 0.chunk.js - 9.1 KB Total Download 231.5 KB 234.1 KB Webpack creates a "chunk" for every lazy loaded module The file 0.chunk.js is loaded when the user navigates to admin The initial download size is smaller with LL The total size over time is bigger with LL because of Webpack async loading The effect of LL start to be noticeable when the app grows
  13. 13. Boot Time Comparison (Prod + AoT) Event Time (No LL) Time (LL) DOM Content Loaded 3.25 s 3.11 s Load 3.27 s 3.25 s FMP 3.30 s 3.16 s Not much difference for an small app Just one lazy loaded module with a couple of components The impact is noticeable for big apps
  14. 14. Preloading (Compare branches normal-lazy-loading vs master )
  15. 15. Enable Preloading Define the property preloadingStrategy in the root module routing import { PreloadAllModules } from '@angular/router'; export const routes: Routes = [ ... ]; @NgModule({ imports: [ RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules }) ], exports: [ RouterModule ], }) export class AppRoutingModule {}
  16. 16. Change Detection
  17. 17. What's Change Detection (CD)? It's a mechanism to keep our "models" in sync with our "views" Change detection is fired when... The user interacts with the app (click, submit, etc.) An async event is completed (setTimeout, promise, observable) When CD is fired, Angular will check every component starting from the top once.
  18. 18. Change Detection Strategy: OnPush Angular offers 2 strategies: Default: Check the entire component when CD is fired OnPush: Check only relevant subtrees when CD is fired OnPush Requirements: Component inputs ( @Input ) need to be immutable objects @Component({ selector: 'rio-workshop', templateUrl: './workshop.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) export class WorkshopComponent { @Input() workshop: Workshop; @Input() isSummary = false; } View Example
  19. 19. Example: The Component Tree
  20. 20. Default Change Detection
  21. 21. OnPush Change Detection
  22. 22. Summary What to do? Apply the OnPush change detection on every component* Never mutate an object or array, always create a a new reference ( )blog // Don't let addPerson = (person: Person): void => { people.push(person); }; // Do let addPerson = (people: Person[], person: Person): Person[] => { return [ ...people, person ]; }; Benefits: Fewer checks of your components during Change Detection Improved overall app performance
  23. 23. Memory Leaks
  24. 24. What's Memory Leak? The increase of memory usage over time
  25. 25. What Causes Memory Leaks in Angular? Main Source => Subscriptions to observables never closed @Injectable() export class WorkshopService { getAll(): Observable<Workshop[]> { ... } } @Component({ selector: 'rio-workshop-list', template: ` <div *ngFor="let workshop of workshops"> {{ workshop.title }} </div>` }) export class WorkshopListComponent implements OnInit { ... ngOnInit() { this.service.getAll().subscribe(workshops => this.workshops = workshops); } }
  26. 26. Manually Closing Connections Before the element is destroyed, close the connection @Component({ selector: 'rio-workshop-list', template: ` <div *ngFor="let workshop of workshops"> {{ workshop.title }} </div>` }) export class WorkshopListComponent implements OnInit, OnDestroy { ... ngOnInit() { this.subscription = this.service.getAll() .subscribe(workshops => this.workshops = workshops); } ngOnDestroy() { this.subscription.unsubscribe(); } }
  27. 27. The async Pipe It closes the connection automatically when the component is destroyed @Component({ selector: 'rio-workshop-list', template: ` <div *ngFor="let workshop of workshops$ | async"> {{ workshop.title }} </div>` }) export class WorkshopListComponent implements OnInit { ngOnInit() { this.workshops$ = this.service.getAll(); } } This is the recommended way of dealing with Observables in your template!
  28. 28. The Http Service Every method of the http services ( get , post , etc.) returns an observable Those observables emit only one value and the connection is closed automatically They won't cause memory leak issues @Component({ selector: 'rio-workshop-list', template: ` <div *ngFor="let workshop of workshops"> {{ workshop.title }} </div>` }) export class WorkshopListComponent implements OnInit { ... ngOnInit() { this.http.get('some-url') .map(data => data.json()) .subscribe(workshops => this.workshops = workshops); } }
  29. 29. Emit a Limited Number of Values RxJs provides operators to close the connection automatically Examples: first() and take(n) This won't cause memory leak issues even if getAll emits multiple values @Component({ selector: 'rio-workshop-list', template: ` <div *ngFor="let workshop of workshops"> {{ workshop.title }} </div>` }) export class WorkshopListComponent implements OnInit { ngOnInit() { this.service.getAll().first() .subscribe(workshops => this.workshops = workshops); } }
  30. 30. Server Side Rendering
  31. 31. Angular Universal Provides the ability to pre-render your application on the server Much faster time to first paint Enables better SEO Enables content preview on social networks Fallback support for older browsers Use the as the base of your applicationuniversal-starter
  32. 32. What's Included Suite of polyfills for the server Server rendering layer Preboot - replays your user's interactions after Angular has bootstrapped State Rehydration - Don't lose your place when the application loads
  33. 33. Boot Time Comparison (Client vs Server) Both environments include previous AoT and Lazy Loading enhancements Event Time (Client) Time (Server) DOM Content Loaded 3.11 s 411 ms Load 3.25 s 2.88 s FMP 3.16 s ~440 ms *Times are on mobile over 3G
  34. 34. Universal Caveats Cannot directly access the DOM constructor(element: ElementRef, renderer: Renderer) { renderer.setElementStyle(element.nativeElement, ‘font-size’, ‘x-large’); } Current solutions only cover Express and ASP.NET servers Project will be migrated into the core Angular repo for v4
  35. 35. Summary
  36. 36. Performance Changes Event JiT AoT Lazy Loading SSR DOM Content Loaded 5.44 s 3.25 s 3.11 s 411 ms Load 5.46 s 3.27 s 3.25 s 2.88 s FMP 5.46 s 3.30 s 3.16 s ~440 ms % Improvement (FMP) 39.6% 4.3% 86.1% *Times are on mobile over 3G
  37. 37. Thank You Slides: https://github.com/rangle/angular-performance-meetup

×