WPO for SPAs
The epic battle against loading indicators
Slide 2
Slide 2 text
Stefan Baumgartner
Internet Batman
Larry Urbano
Senior Sales Engineer
Monitoring redefined
Slide 3
Slide 3 text
Agenda
1. Some theory
2.We meet our Single Page Application
3.Performance optimisation techniques
4.Some live coding and lots of demos
Slide 4
Slide 4 text
Title Text
Breaks
Slide 5
Slide 5 text
Subheadline
Slide 6
Slide 6 text
Why have we moved to SPAs?
Slide 7
Slide 7 text
Client
Client
Initial request
HTML payload
Form POST
HTML payload
Traditional
Slide 8
Slide 8 text
Client
Client
Initial request
HTML payload
AJAX call via JS
HTML Diff
SPA
Slide 9
Slide 9 text
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
Slide 10
Slide 10 text
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
Slide 11
Slide 11 text
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
Slide 12
Slide 12 text
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?
Slide 13
Slide 13 text
No content
Slide 14
Slide 14 text
Subheadline
Slide 15
Slide 15 text
initial HTML request
angular.js
main.js
data/from/backend
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
Slide 21
Slide 21 text
Let’s check our SPA
Demo-time
Slide 22
Slide 22 text
No content
Slide 23
Slide 23 text
cd /app/twitterwall-server
npm start
service nginx start
Slide 24
Slide 24 text
cd /app/twitterwall-client-webpack
(commands to follow)
Slide 25
Slide 25 text
replace contents of
/app/twitterwall-server/public
with
/app/twitterwall-client-webpack/dist
Slide 26
Slide 26 text
npm stop
npm start
Slide 27
Slide 27 text
Step 1: Production builds
Put back your development pride
Slide 28
Slide 28 text
CSS
JS
Slide 29
Slide 29 text
CSS
JS
Slide 30
Slide 30 text
CSS
JS VENDOR
Slide 31
Slide 31 text
CSS
JS
VENDOR
Slide 32
Slide 32 text
Step 2: Tree shaking
It’s not as funny as it sounds. But equally cool
Slide 33
Slide 33 text
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}
}
Slide 34
Slide 34 text
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.
Slide 35
Slide 35 text
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.
Slide 36
Slide 36 text
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
Slide 37
Slide 37 text
Step 3: SSR
Putting the server back into the equation
Slide 38
Slide 38 text
initial HTML request
angular.js
main.js
data/from/backend
Start render
Slide 39
Slide 39 text
initial HTML request
angular.js
main.js
data/from/backend
Start render?
Slide 40
Slide 40 text
The network is a bottle-neck
Slide 41
Slide 41 text
So make every request count!
Slide 42
Slide 42 text
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
Slide 43
Slide 43 text
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
Slide 44
Slide 44 text
Important content first
Everything else is an enhancement
Slide 45
Slide 45 text
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
Slide 46
Slide 46 text
No content
Slide 47
Slide 47 text
No content
Slide 48
Slide 48 text
No content
Slide 49
Slide 49 text
But I can’t move all by backend to
Node.js
Slide 50
Slide 50 text
You don’t have to!
Slide 51
Slide 51 text
No content
Slide 52
Slide 52 text
Bonus round!
Lazy loaded routes
Slide 53
Slide 53 text
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…
Slide 54
Slide 54 text
Bonus round!
Responsive images
Slide 55
Slide 55 text
Slide 56
Slide 56 text
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
Slide 57
Slide 57 text
s
Subheadline
Speed Index
Slide 58
Slide 58 text
No content
Slide 59
Slide 59 text
No content
Slide 60
Slide 60 text
∫ 1 - visuallycomplete/100
0
end
Slide 61
Slide 61 text
What does this mean?
Slide 62
Slide 62 text
No content
Slide 63
Slide 63 text
No content
Slide 64
Slide 64 text
No content
Slide 65
Slide 65 text
No content
Slide 66
Slide 66 text
Visually complete (%)
0
25
50
75
100
Time in Seconds
0s 1s 2s 3s 4s 5s 6s 7s 8s
Slide 67
Slide 67 text
Visually complete (%)
0
25
50
75
100
Time in Seconds
0s 1s 2s 3s 4s 5s 6s 7s 8s
Slide 68
Slide 68 text
Visually complete (%)
0
25
50
75
100
Time in Seconds
0s 1s 2s 3s 4s 5s 6s 7s 8s
Slide 69
Slide 69 text
s
Subheadline
Thoughts
about HTTP2
Slide 70
Slide 70 text
Server
Client
HTTP/2
Getting stuff …
GET
image1
image1
header
image1
payload
image1
payload
image2
header
image2
payload
image1
payload
image2
payload
GET
image2
Slide 71
Slide 71 text
HTTP 1.1
index.html
a.js
b.js
c.js
d.js
Slide 72
Slide 72 text
HTTP 2
index.html
a.js
b.js
c.js
d.js
Slide 73
Slide 73 text
HTTP 2
index.html
a.js
b.js
c.js
d.js
Slide 74
Slide 74 text
HTTP 2
index.html
a.js
b.js
c.js
d.js
Slide 75
Slide 75 text
No content
Slide 76
Slide 76 text
Desktop
HTTP/2 ~1.8s
HTTP1.1 ~2.6s
Slide 77
Slide 77 text
mobile connections
HTTP1.1 ~3.37s
HTTP2 ~1.72
Slide 78
Slide 78 text
A slow website on HTTP1.1 will
still be a slow website on HTTP2
Slide 79
Slide 79 text
Frequency of change
Libraries
Utilities
Module Module Module Module
rigid
high
frequency
some
frequency
Slide 80
Slide 80 text
Optimised utility layer
Libraries
Utilities
Module Module Module
rigid
high
frequency
some
frequency
Slide 81
Slide 81 text
Extending the utility layer
Libraries
Utilities
Module Module Module
rigid
high
frequency
some
frequency
Slide 82
Slide 82 text
Files to change
Libraries
Utilities
Module Module Module
rigid
high
frequency
some
frequency
Slide 83
Slide 83 text
Frequency of change
Libraries
Module Module Module
rigid
high
frequency
Module
Slide 84
Slide 84 text
What to do with
your application?
Slide 85
Slide 85 text
The best request is
a request not being made
Slide 86
Slide 86 text
Create independent,
exchangeable components
Slide 87
Slide 87 text
Create small,
detached bundles
Slide 88
Slide 88 text
Code duplication and weight is okay
if the file can stay longer
Slide 89
Slide 89 text
Think about long lasting applications
and frequency of change