1. Intercept click
2. Request HTML over Ajax
3. Update and
4. Push new browser history state
PJAX
Slide 20
Slide 20 text
✓ No server side conditionals
✓ Minimal markup changes
✓ Graceful degradation
✓ Preserves Back button functionality
Slide 21
Slide 21 text
What if we could pre-fetch the
next page?
Slide 22
Slide 22 text
Okay, but which page?
Slide 23
Slide 23 text
Let the user show the way…
mouse pointer
Slide 24
Slide 24 text
Prefetch request
Link
Link Link
Regular request
✓
Slide 25
Slide 25 text
Is this really significant?
Slide 26
Slide 26 text
No content
Slide 27
Slide 27 text
Pre-fetch page on
mouseover/touchstart
Slide 28
Slide 28 text
✓ At least 300ms of gain in speed
✓ Clicks will start to appear instant
✓ Again, no extra config on the server
Slide 29
Slide 29 text
Demo: buuuk.com
Slide 30
Slide 30 text
How can you implement it?
Slide 31
Slide 31 text
InstantClick
Slide 32
Slide 32 text
#2
Slide 33
Slide 33 text
No content
Slide 34
Slide 34 text
No content
Slide 35
Slide 35 text
~3 million monthly average
~72 concurrent (peak)
~150 concurrent (future)
Slide 36
Slide 36 text
Response time target: 200ms
Slide 37
Slide 37 text
Server
HTTP Server WebApp / CMS Database
Browser
Slide 38
Slide 38 text
Requested page is regenerated
each time
Slide 39
Slide 39 text
Save a copy of the final page
Slide 40
Slide 40 text
Server
HTTP Server WebApp / CMS Database
Cache
Slide 41
Slide 41 text
Now the server can handle load
Slide 42
Slide 42 text
But cache may be out of sync
Slide 43
Slide 43 text
So, we need to invalidate cache
(based on some trigger)
Slide 44
Slide 44 text
How?
Slide 45
Slide 45 text
There are only two hard things in
Computer Science: cache invalidation
and naming things.”
– Phil Karlton
“
Slide 46
Slide 46 text
3 options
Slide 47
Slide 47 text
A. Delete, rebuild on request
B. Delete, rebuild immediately
C. Rebuild on request, replace
Slide 48
Slide 48 text
Delete
Delete,
Rebuild
Rebuild,
Replace
No out-of-sync pages returned ✓ ✓ ×
Cache regenerates automatically ✓ × ✓
Server load is distributed ✓ × ✓
All users get a cached response
× – ✓
Slide 49
Slide 49 text
Speed > accuracy*, so
C. Rebuild on request, replace
* in this case
Slide 50
Slide 50 text
Okay, but what should
trigger invalidation?
Slide 51
Slide 51 text
A. Expire on change in the App
B. Time based expiry
Slide 52
Slide 52 text
Change Time
No redundant invalidation ✓ ×
Staggered expiry of caches × ✓
Cache layer decoupled from App × ✓
Slide 53
Slide 53 text
Decoupled > no redundancy*, so
B. Time based expiry
* in this case
Slide 54
Slide 54 text
Expiry times as short as
one second
Slide 55
Slide 55 text
1. Full page cache
2. Short, time based expiry
3. Re-generate, then replace
Microcaching
Slide 56
Slide 56 text
✓ All users get a cached response
✓ Cached content no older than 2 seconds
✓ Cache layer decoupled from App layer
✓ Staggered expiry & regeneration
✓ Reduce global latency
✓ Reduce server load
✓ Save bandwidth
✓ Zero-config
Slide 68
Slide 68 text
No content
Slide 69
Slide 69 text
Second – Prioritise Critical Path
Slide 70
Slide 70 text
No content
Slide 71
Slide 71 text
No content
Slide 72
Slide 72 text
From 30 to 3 images
Slide 73
Slide 73 text
1. Prioritise critical rendering path
2. Defer loading images that are
not visible
3. Visual feedback that improves
perception of speed
Lazy loading
Slide 74
Slide 74 text
github.com/aFarkas/lazysizes →
Slide 75
Slide 75 text
Third – Appropriate no. of pixels
Slide 76
Slide 76 text
Nautilus.jpg
1200x674
Slide 77
Slide 77 text
400x224 800x449 1200x674 1200x674
Slide 78
Slide 78 text
1. Create different sized images
2. Use srcset attribute to
inform browser
3. Use sizes attribute to help
browser choose the right size
Responsive
Images
Slide 79
Slide 79 text
✓ Fewer bytes to download
✓ Fewer pixels to decode
✓ Future-proof for higher DPI screens