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. 2.

    @yourtwitter Description or Image @twitterhandle Agenda • Network performance •

    Runtime performance • Good practices • Application in production • Initial rendering
  2. 4.

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

    • Lazy loading • Preloading & prefetching • Server-side rendering • Write efficient code
  3. 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
  4. 10.

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

    tags Step 2: Download right version Differential loading
  5. 11.

    @mgechev Step 1: Load HTML Step 2: Request JS Differential

    serving Step 3: Return JS based on userAgent
  6. 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>
  7. 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>
  8. 15.
  9. 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
  10. 22.
  11. 23.
  12. 26.
  13. 27.

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

    'settings', loadChildren: './settings/settings.module#SettingsModule' }, { path: 'article', loadChildren: './article/article.module#ArticleModule' } ];
  14. 28.

    @yourtwitter Route-based code-splitting in Ivy const routes: Routes = [

    { path: 'settings', loadChildren: import('./settings/settings.module') .then(m => m.SettingsModule); },
 ... ];
  15. 29.

    @yourtwitter Route-based code-splitting in Ivy const routes: Routes = [

    { path: 'settings', loadChildren: import('./settings/settings.module') .then(m => m.SettingsModule); },
 ... ]; Experimental
  16. 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
  17. 31.
  18. 32.
  19. 34.
  20. 35.
  21. 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
  22. 40.
  23. 42.

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

    @NgModule({ imports: [RouterModule.forRoot(routes, { preloadingStrategy: QuicklinkStrategy })], exports: [RouterModule] }) export class AppRoutingModule {}
  24. 43.

    @yourtwitter Prefetch visible links import { QuicklinkModule } from 'ngx-quicklink';

    @NgModule({ imports: [ ... QuicklinkModule ], exports: [ ... QuicklinkModule, ] }) export class SharedModule {}
  25. 45.
  26. 46.
  27. 48.

    @mgechev A performance budget is a limit for pages which

    the team is not allowed to exceed. Addy Osmani
  28. 53.
  29. 57.

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

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  30. 58.

    @yourtwitter @mgechev • Faster initial contentful paint • Better SEO

    • Better time to interactive? Benefits of SSR
  31. 59.

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

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  32. 60.

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

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  33. 74.

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

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  34. 75.

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

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  35. 76.

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

    3: Paint & load JS Server-side rendering Step 4: Bootstrap app
  36. 83.

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

    (rf & 1) { // Create } if (rf & 2) { ɵtextBinding(3, ɵinterpolation1(" ", ctx.comment.body, " " ...)); }
  37. 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
  38. 86.

    @yourtwitter @mgechev In collaboration with v8 team to make sure

    we generate code optimizable by the JavaScript engine Monomorphic code
  39. 87.

    @yourtwitter @mgechev Summary • Reducing the bundle size • Speeding

    up user navigations • Automated deployment via CLI • Progressive rehydration • Compile-time optimizations