Building Fast Angular Applications By Default

Building Fast Angular Applications By Default

Angular grew significantly in the past few years from both a tooling and developer experience standpoint. This talk will explore many of the features and newer improvements in the pipeline that allow anyone to build and deploy performant apps with very little overhead. Through real demos and examples, we’ll cover Ivy, bundle budgeting, differential serving, automatic code-splitting, and progressive rehydration of SSR elements. In the second part of the talk, we’ll focus on how to efficiently prefetch and preload different modules and components.

82bafb0432ce4ccc9dcc26f94d5fe5bc?s=128

Minko Gechev

April 06, 2019
Tweet

Transcript

  1. @mgechev Building Fast Angular Applications by Default Minko Gechev twitter.com/mgechev


    github.com/mgechev
 blog.mgechev.com
  2. @yourtwitter Description or Image @twitterhandle Agenda • Network performance •

    Runtime performance • Good practices • Application in production • Initial rendering
  3. @yourtwitter Network performance Description or Image @twitterhandle

  4. @yourtwitter @mgechev Good practices • Ship fewer bytes of JavaScript

    • Lazy loading • Preloading & prefetching • Server-side rendering • Write efficient code
  5. @yourtwitter Shipping less JavaScript

  6. @yourtwitter @mgechev • Minification/dead code elimination • Differential loading or

    serving • Code-splitting Shipping fewer bytes
  7. @yourtwitter @mgechev • Minification/dead code elimination • Differential loading or

    serving • Code-splitting Shipping fewer bytes
  8. @yourtwitter @mgechev Differential loading • Produce ES5 bundles for newer

    browsers • Do not send polyfills to modern browsers • Smaller payload • Do not downlevel modern features • Faster execution • Smaller payload
  9. @mgechev -40KB polyfills -7% each bundle

  10. @mgechev Step 1: Load HTML Step 2: Look at script

    tags Step 2: Download right version Differential loading
  11. @mgechev Step 1: Load HTML Step 2: Request JS Differential

    serving Step 3: Return JS based on userAgent
  12. @yourtwitter @mgechev Differential loading ✅ Simple deployment infrastructure ✅ Proposal

    for a browser standard WHATWG
  13. @yourtwitter Differential loading <!DOCTYPE html> <html lang="en"> <head> <title>Differential loading

    </title> </head> <body> <script type="module" src="app.mjs"> </script> <script nomodule src="app.js"> </script> </body> </html>
  14. @yourtwitter Differential loading <!DOCTYPE html> <html lang="en"> <head> <title>Differential loading

    </title> </head> <body> <script type="module" src="app.mjs"> </script> <script nomodule src="app.js"> </script> </body> </html>
  15. @mgechev

  16. @yourtwitter Angular CLI Introduced this feature in v8.0.0

  17. @yourtwitter @mgechev • Set the target in tsconfig.json to es2015

    • Set the minimum supported browsers in browserlist Differential loading with Angular CLI version 8
  18. @yourtwitter @mgechev • Minification/dead code elimination • Differential loading or

    serving • Code-splitting Shipping fewer bytes
  19. twitter.com/mgechev lazy-loading

  20. @yourtwitter @mgechev • Component-level • Route-level Code-splitting could be

  21. @yourtwitter @mgechev • Component-level • Route-level Code-splitting could be

  22. @mgechev

  23. @mgechev

  24. @mgechev https://www.youtube.com/watch?v=MMPl9wHzmS4

  25. @yourtwitter @mgechev • Component-level • Route-level Code-splitting could be

  26. @mgechev

  27. @yourtwitter Route-based code-splitting const routes: Routes = [ { path:

    'settings', loadChildren: './settings/settings.module#SettingsModule' }, { path: 'article', loadChildren: './article/article.module#ArticleModule' } ];
  28. @yourtwitter Route-based code-splitting in Ivy const routes: Routes = [

    { path: 'settings', loadChildren: import('./settings/settings.module') .then(m => m.SettingsModule); },
 ... ];
  29. @yourtwitter Route-based code-splitting in Ivy const routes: Routes = [

    { path: 'settings', loadChildren: import('./settings/settings.module') .then(m => m.SettingsModule); },
 ... ]; Experimental
  30. @yourtwitter @mgechev 1. Definition of a lazy module 2. Declaration

    of a lazy route 3. Definition of a component 4. Declaration of a eager route Steps for creating a lazy-loaded module
  31. @mgechev

  32. @yourtwitter Route-based code-splitting with the future Angular CLI $ ng

    g module about --route=about --module=index
  33. @yourtwitter @mgechev Questions

  34. @mgechev

  35. @mgechev

  36. twitter.com/mgechev Step 1: Open https://example.com/ Step 2: Determine JavaScript which

    is likely to be required Step 3: Download the chunks Step 4: Store chunks in browser cache Pre-fetching
  37. twitter.com/mgechev

  38. @yourtwitter @mgechev • Prefetch visible links • Predictive prefetching •

    Prefetch on mouse over Prefetching strategies
  39. @yourtwitter @mgechev • Prefetch visible links • Predictive prefetching •

    Prefetch on mouse over Prefetching strategies
  40. @mgechev

  41. @yourtwitter Prefetch visible links $ npm install ngx-quicklink

  42. @yourtwitter Prefetch visible links import { QuicklinkStrategy } from 'ngx-quicklink';

    @NgModule({ imports: [RouterModule.forRoot(routes, { preloadingStrategy: QuicklinkStrategy })], exports: [RouterModule] }) export class AppRoutingModule {}
  43. @yourtwitter Prefetch visible links import { QuicklinkModule } from 'ngx-quicklink';

    @NgModule({ imports: [ ... QuicklinkModule ], exports: [ ... QuicklinkModule, ] }) export class SharedModule {}
  44. @yourtwitter @mgechev • Prefetch visible links • Predictive prefetching •

    Prefetch on mouse over Prefetching strategies
  45. @mgechev

  46. @mgechev

  47. @mgechev early alpha

  48. @mgechev A performance budget is a limit for pages which

    the team is not allowed to exceed. Addy Osmani
  49. @yourtwitter Performance Budgets enforces constraints to let you have guarantees

    v8.0.0 https://angular.io/guide/build
  50. @yourtwitter Angular projects without compression >27%

  51. @yourtwitter >80% Angular projects without CDN

  52. @yourtwitter ng deploy $ ng add [PROVIDER] $ ng run

    app:deploy
  53. @mgechev

  54. @mgechev Partnering with

  55. @yourtwitter @mgechev Questions

  56. @yourtwitter Server-side rendering

  57. @mgechev Step 1: Request page Step 2: Render page Step

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  58. @yourtwitter @mgechev • Faster initial contentful paint • Better SEO

    • Better time to interactive? Benefits of SSR
  59. @mgechev Step 1: Request page Step 2: Render page Step

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  60. @mgechev Step 1: Request page Step 2: Render page Step

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  61. @mgechev https://addyosmani.com/blog/rehydration/

  62. twitter.com/mgechev Destructive Rehydration DOM Component tree

  63. twitter.com/mgechev Progressive Rehydration DOM ( )

  64. twitter.com/mgechev Progressive Rehydration DOM ( )

  65. twitter.com/mgechev ( ) Progressive Rehydration DOM

  66. twitter.com/mgechev ( ) Progressive Rehydration DOM

  67. twitter.com/mgechev ( ) Progressive Rehydration DOM ChildCmp1

  68. twitter.com/mgechev ( ) Progressive Rehydration DOM ChildCmp1

  69. twitter.com/mgechev ( ) Progressive Rehydration DOM ChildCmp1

  70. twitter.com/mgechev ( ) Progressive Rehydration DOM ChildCmp1 ChildCmp2

  71. twitter.com/mgechev ( ) Progressive Rehydration DOM ChildCmp1 ChildCmp2

  72. twitter.com/mgechev ( ) Progressive Rehydration DOM RootCmp ChildCmp1 ChildCmp2

  73. @yourtwitter Progressive bootstrapping

  74. @mgechev Step 1: Request page Step 2: Render page Step

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  75. @mgechev Step 1: Request page Step 2: Render page Step

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  76. @mgechev Step 1: Request page Step 2: Render page Step

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  77. twitter.com/mgechev Progressive loading DOM

  78. twitter.com/mgechev Progressive loading DOM ⌨ Key down

  79. twitter.com/mgechev Progressive loading DOM ChildCmp

  80. @yourtwitter Faster Rendering

  81. @yourtwitter @mgechev • Discovery of dependencies • Efficient code generation

    • Efficient runtime Runtime optimizations
  82. @mgechev Model View dependencies Compiler
 
 
 
 Front-end Back-end

    Input Output
  83. @mgechev <p class="card-text"> {{ comment.body + 'foo' }} </p> if

    (rf & 1) { // Create } if (rf & 2) { ɵtextBinding(3, ɵinterpolation1(" ", ctx.comment.body, " " ...)); }
  84. @yourtwitter @mgechev • Tree-shakeable code • Monomorphic executions Efficient code

    generation
  85. @mgechev Tree-shakeable code import { ɵelementStart, … } from ...

    if (rf & 1) { ɵelementStart(0, "div", _c0); ɵelementStart(2, "p", _c2); ɵtext(3); ɵelementEnd(); ɵelementEnd(); } if (rf & 2) { ɵtextBinding(3, ... ɵinterpolation1( ...) } The compiler imports only what given component needs
  86. @yourtwitter @mgechev In collaboration with v8 team to make sure

    we generate code optimizable by the JavaScript engine Monomorphic code
  87. @yourtwitter @mgechev Summary • Reducing the bundle size • Speeding

    up user navigations • Automated deployment via CLI • Progressive rehydration • Compile-time optimizations
  88. @yourtwitter @mgechev Questions

  89. @mgechev Thank you! twitter.com/mgechev
 github.com/mgechev
 blog.mgechev.com