Pro Yearly is on sale from $80 to $50! »

Web performance optimisation for single page applications

Web performance optimisation for single page applications

Accompanying slides to a 4 hour course on monitoring and web performance optimisation for single page applications

187d92c9284160ad908885ab096f5209?s=128

Stefan Baumgartner

February 06, 2017
Tweet

Transcript

  1. WPO for SPAs The epic battle against loading indicators

  2. Stefan Baumgartner Internet Batman Larry Urbano Senior Sales Engineer Monitoring

    redefined
  3. Agenda 1. Some theory 2.We meet our Single Page Application

    3.Performance optimisation techniques 4.Some live coding and lots of demos
  4. Title Text Breaks

  5. Subheadline

  6. Why have we moved to SPAs?

  7. Client Client Initial request HTML payload Form POST HTML payload

    Traditional
  8. Client Client Initial request HTML payload AJAX call via JS

    HTML Diff SPA
  9. Single Page Applications are awesome … ▪ They provide better

    UX once loaded ▪ Communication is reduced to deltas ▪ This results in fewer requests and smaller payload ▪ Should your Network die, you still have some content available ▪ They’re super-easy to deploy
  10. Single Page Applications are hard… ▪ The client is in

    control… but the client starts when everything has been transferred ▪ The client side app has to take care of all the errors and has to be a lot lot smarter ▪ Flaky networks harm the UX ▪ Fallbacks are hard ▪ Bad practices are more seductive ▪ States are hard to share
  11. Client Client Initial request non-content HTML AJAX call via JS

    content diff SPAs Resource request JavaScript payload Initial AJAX call via JS content payload
  12. Client Client Initial request non-content HTML AJAX call via JS

    content diff SPAs Resource request JavaScript payload Initial AJAX call via JS content payload What is going on here?
  13. None
  14. Subheadline

  15. initial HTML request angular.js main.js data/from/backend

  16. All of them?

  17. prompt for unload redirect DNS TCP Request Response Processing onLoad

    navigationStart redirectStart redirectEnd domainLookupStart domainLookupEnd connectStart connectEnd requestStart responseStart responseEnd domLoading domInteractive domContentLoaded domComplete loadEventStart loadEventEnd
  18. prompt for unload redirect DNS TCP Request Response Processing onLoad

    navigationStart redirectStart redirectEnd domainLookupStart domainLookupEnd connectStart connectEnd requestStart responseStart responseEnd domLoading domInteractive domContentLoaded domComplete loadEventStart loadEventEnd
  19. domLoading domInteractive domContentLoaded domComplete

  20. domLoading domInteractive domContentLoaded domComplete The DOM is getting parsed DOM

    is parsed and ready to work on The document is loaded (wo stylesheets, images) All sub resources are loaded
  21. Let’s check our SPA Demo-time

  22. None
  23. cd /app/twitterwall-server npm start service nginx start

  24. cd /app/twitterwall-client-webpack (commands to follow)

  25. replace contents of /app/twitterwall-server/public with /app/twitterwall-client-webpack/dist

  26. npm stop npm start

  27. Step 1: Production builds Put back your development pride

  28. CSS JS

  29. CSS JS

  30. CSS JS VENDOR

  31. CSS JS VENDOR

  32. Step 2: Tree shaking It’s not as funny as it

    sounds. But equally cool
  33. ESnext module syntax ▪ EcmaScript finally has a module syntax

    (and probably a module loading strategy soon as well!) ▪ Tooling allows us to use this new syntax already import { createServer } from ‘http’; import * as path from ‘path’; export function cube(x) { return x*x*x; } export default { … } const createServer = require(‘http’).createServer; const path = require(‘path’); module.exports = { cube: function(x) { return x*x*x} }
  34. Tree Shaking ▪ This new syntax allows tools to do

    a static code analysis based on the JavaScript AST. ▪ With that, we can exclude functions we simply do not need, reducing our bundle size even more.
  35. Angular Ahead of Time compilation ▪ Faster rendering: With AOT,

    the browser downloads a pre-compiled version of the application. The browser loads executable code so it can render the application immediately, without waiting to compile the app first. ▪ Fewer asynchronous requests: The compiler inlines external html templates and css style sheets within the application JavaScript, eliminating separate ajax requests for those source files.
  36. Angular Ahead of Time compilation ▪ Smaller Angular framework download

    size: There’s no need to download the Angular compiler if the app is already compiled. The compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload. ▪ Detect template errors earlier: The AOT compiler detects and reports template binding errors during the build step before users can see them. ▪ Better security: AOT compiles HTML templates and components into JavaScript files long before they are served to the client. With no templates to read and no risky client-side HTML or JavaScript evaluation, there are fewer opportunities for injection attacks
  37. Step 3: SSR Putting the server back into the equation

  38. initial HTML request angular.js main.js data/from/backend Start render

  39. initial HTML request angular.js main.js data/from/backend Start render?

  40. The network is a bottle-neck

  41. So make every request count!

  42. Client Client Initial request non-content HTML AJAX call via JS

    content diff Resource request JavaScript payload Initial AJAX call via JS content payload App
  43. Client Client Initial request Initial Render HTML AJAX call via

    JS content diff Resource request JavaScript payload Initial AJAX call via JS content payload App App
  44. Important content first Everything else is an enhancement

  45. Server side rendering for SPAs ▪ Thanks to a little

    technology called Node.js, we are able to render JS on the client and the server ▪ As long as you have valid routes (= URLs), you have the ability to render the state on the server ▪ The first requests bring the rendered state ▪ Then the JavaScript framework kicks in
  46. None
  47. None
  48. None
  49. But I can’t move all by backend to Node.js

  50. You don’t have to!

  51. None
  52. Bonus round! Lazy loaded routes

  53. Bundling … ▪ Why bundle everything, when we just need

    a few things to start? ▪ Routes deep down in the navigation might not be used at all… ▪ Bundle by routes, split away code that you don’t need at first…
  54. Bonus round! Responsive images

  55. <img src=”screenshot-600.png” srcset="screenshot-200.png 200w, screenshot-400.png 400w, screenshot-600.png 600w, screenshot-800.png 800w,

    screenshot-1000.png 1000w, screenshot-1200.png 1200w, screenshot-1400.png 1400w, screenshot-1600.png 1600w” sizes="(min-width: 900px) 50vw, 100vw" alt=”Super screenshot of our product.">
  56. <img src=”screenshot-600.png” srcset="screenshot-200.png 200w, screenshot-400.png 400w, screenshot-600.png 600w, screenshot-800.png 800w,

    screenshot-1000.png 1000w, screenshot-1200.png 1200w, screenshot-1400.png 1400w, screenshot-1600.png 1600w” sizes="(min-width: 900px) 50vw, 100vw" alt=”Super screenshot of our product."> A low-res fallback image for browsers that don’t know srcset These sources are available. For each “width unit” there’s a reduced version of our original screenshot The sizes define which source to choose from. Retina screens are also checked
  57. s Subheadline Speed Index

  58. None
  59. None
  60. ∫ 1 - visuallycomplete/100 0 end

  61. What does this mean?

  62. None
  63. None
  64. None
  65. None
  66. Visually complete (%) 0 25 50 75 100 Time in

    Seconds 0s 1s 2s 3s 4s 5s 6s 7s 8s
  67. Visually complete (%) 0 25 50 75 100 Time in

    Seconds 0s 1s 2s 3s 4s 5s 6s 7s 8s
  68. Visually complete (%) 0 25 50 75 100 Time in

    Seconds 0s 1s 2s 3s 4s 5s 6s 7s 8s
  69. s Subheadline Thoughts about HTTP2

  70. Server Client HTTP/2 Getting stuff … GET image1 image1 header

    image1 payload image1 payload image2 header image2 payload image1 payload image2 payload GET image2
  71. HTTP 1.1 index.html a.js b.js c.js d.js

  72. HTTP 2 index.html a.js b.js c.js d.js

  73. HTTP 2 index.html a.js b.js c.js d.js

  74. HTTP 2 index.html a.js b.js c.js d.js

  75. None
  76. Desktop HTTP/2 ~1.8s HTTP1.1 ~2.6s

  77. mobile connections HTTP1.1 ~3.37s HTTP2 ~1.72

  78. A slow website on HTTP1.1 will still be a slow

    website on HTTP2
  79. Frequency of change Libraries Utilities Module Module Module Module rigid

    high frequency some frequency
  80. Optimised utility layer Libraries Utilities Module Module Module rigid high

    frequency some frequency
  81. Extending the utility layer Libraries Utilities Module Module Module rigid

    high frequency some frequency
  82. Files to change Libraries Utilities Module Module Module rigid high

    frequency some frequency
  83. Frequency of change Libraries Module Module Module rigid high frequency

    Module
  84. What to do with your application?

  85. The best request is a request not being made

  86. Create independent, exchangeable components

  87. Create small, detached bundles

  88. Code duplication and weight is okay if the file can

    stay longer
  89. Think about long lasting applications and frequency of change

  90. Thank you.