74
To push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

  • Upload
    others

  • View
    15

  • Download
    0

Embed Size (px)

Citation preview

Page 1: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

To push, or not to push?! A journey of resource loading in the browser

JSConf EU, June 2018

Patrick Hamann @patrickhamann

Page 2: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann
Page 3: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Why?

Page 4: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

“HTTP/2 will solve this” – Everybody

Page 5: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Resource loading in the browser is hard.

Page 6: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Resource loading is hard:

⏱ Performance is tightly coupled to latency

🤝 Connection cost is high

📈 Congestion control is unavoidable

🙈 Critical resources can be hidden

Bandwidth is often under-utilised

⚠ Script execution is expensive

💤

Page 7: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

How can we load our resources most efficiently?

Page 8: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann
Page 9: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

A critical request is one that contains an asset that is essential to the content within the users viewport. – Ben Schwarz, Calibre

Page 10: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

What are my critical resources?

✅ Critical CSS for current route

✅ Fonts

✅ Hero images

✅ Initial application route

✅ Application bootstrap data

Page 11: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

User navigates

First Contentful Paint

First Meaningful Paint

Time to Interactive

Visually Complete

Page 12: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

User navigates

First Contentful Paint

First Meaningful Paint

Time to Interactive

Visually Complete

Page 13: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

A good loading strategy:

✅ Prioritises above-the-fold rendering

✅ Prioritises interactivity

✅ Is easy to use

✅ Is measurable

Page 14: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Preload

Page 15: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Request page

Network

Renderer

GET html

Build DOM

response

Build CSSOM First paint

GET css response

idle idle

Render blocking

GET font response

Text paint

Text blocking

Render tree

😢

Page 16: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Provides a declarative fetch primitive that initiates an early fetch and separates fetching from resource execution.

Page 17: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

1 <!-- preload stylesheet resource via declarative markup --> 2 <link rel="preload" href="/styles.css" as="style"> 3 4 <!-- or, preload stylesheet resource via JavaScript --> 5 <script> 6 const res = document.createElement("link"); 7 res.rel = "preload"; 8 res.as = "style"; 9 res.href = "lazy-loaded-styles.css"; 10 document.head.appendChild(res); 11 </script>

1 Link: <my-awesome-font.woff>; rel=preload; as=font; crossorigin 2 Link: <application-data.json>; rel=preload; as=fetch; 3 Link: <sub-module.mjs>; rel=modulepreload;

Preload with markup:

Preload with HTTP header:

Page 18: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Before

Page 19: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

After

Page 20: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Shopify’s switch to preloading fonts saw a 50% (1.2 second) improvement in time-to-text-paint. This removed their flash-of-invisible text completely.– Shopify

Page 21: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Are indicating resource hints via the HTML response too late?

Page 22: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Server push

Page 23: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Client CDN/Surrogate/Server Origin

Time

GET /index.htmlGET /index.html

/index.html200

GET main.css

GET /main.css

/index.html200

Server think time

😢

Page 24: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Client CDN/Surrogate/Server Origin

Time

GET /index.htmlGET /index.html

/index.html

Link: <main.css>; rel=prel

oad

PUSH_PROMISE main.css

/index.html

main.css

200

Server think time

Page 25: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

So how can I push?

Page 26: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

1 Link: <font.woff2>; rel=preload; as=font crossorigin

Indicate push via preload Link header.

1 Link: <main.css>; rel=preload; as=style; nopush

Use no push attribute to disable push

semantics and only use preload.

1 Link: <application.js>; rel=preload; as=style; x-http2-push-only

Fastly uses x-http2-push-only attribute to disable preload semantics

Page 27: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Push

No Push

index.html

main.css

app.js

font.woff

Time

index.html

main.css

app.js

font.woff

Time

1 RTT saving!

Page 28: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

After

index.html

main.css

app.js

font.woff

Time

Idle

😢

Page 29: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Client CDN/Surrogate/Server Origin

Time

GET /index.htmlGET /index.html

/index.html

Link: <main.css>; rel=prel

oad

PUSH_PROMISE main.css

/index.html

main.css

200

Server think time

😢

Page 30: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Server push benefits:

✅ 1 RTT saving

✅ Useful for long server think time

✅ Useful for long RTT times

⚠ Link header indication is too late

Page 31: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Is indicating push via the HTML response too late?

Page 32: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Async push

Page 33: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Client CDN/Surrogate/Server Origin

Time

😎

GET /index.htmlGET /index.html

PUSH_PROMISE main.css

/index.html

main.css

Server think time

/index.html200

Page 34: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

1 const http2 = require('http2'); 2 3 function handler(request, response) { 4 if (request.url === "/index.html") { 5 const push = response.push('/critical.css'); 6 push.writeHead(200); 7 fs.createReadStream('/critical.css').pipe(push); 8 } 9 10 // Generate index response: 11 // - Fetch data from DB 12 // - Render template 13 // etc ... 14 15 response.end(data); 16 } 17 18 const server = http2.createServer(opts, handler); 19 server.listen(80);

Page 35: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Async push

Push

index.html

main.css

app.js

font.woff

Time

index.html

main.css

app.js

font.woff

Time

Page 36: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Utilising idle network server think time == win!

index.html

main.css

app.js

font.woff

Time

😎

Page 37: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

What about the repeat view?

Page 38: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

index.html

main.css

app.js

font.woff

Time

(from disk cache)

(from disk cache)

Repeat view

index.html

main.css

app.js

font.woff

Time

First view

Page 39: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Nikkei.com - Web performance made easy: Addy Osmani, Ewa Gasperowicz https://youtu.be/Mv-l3-tJgGk

Page 40: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

The server has no knowledge of client cache state.

Page 41: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

So what’s the problem?

Page 42: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Client CDN/Surrogate/Server

Time

@patrickhamann

GET /index.html

PUSH_PROMISE main.css

main.css

RST_STREAM main.css

Page 43: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Client CDN/Surrogate/Server

Time

@patrickhamann

GET /index.html

PUSH_PROMISE main.css

main.css

RST_STREAM main.css

Page 44: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

HTTP cacheService Worker

Push cache

Push cache

Memory cache

Memory cache

Page

Page

Server

Separate push cache per

HTTP/2 connection.

Page 45: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Push cache semantics

⚠ Connection must be authoritative

⚠ Cache per HTTP/2 connection

⚠ Items can only be claimed once

⚠ It’s the last cache

⚠ It’s not spec’d

Page 46: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

HTTP/2 push is tougher than I thought – Jake Archibald https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/

Page 47: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

HTTP/2 Server Push - Browser inconsistencies

✅ ✅ ⚠ ⚠

Page 48: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

0.008% of requests on the Fastly network are push initiated.

Page 49: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

When should I push?

✅ You have long RTTs or server processing

✅ You can use async push

✅ You have a client-rendered app shell (PRPL)

✅ You control the client (native, Electron etc)

Page 50: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Is the 1 RTT saving worth the complexity?

Page 51: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Are there other solutions?

Page 52: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

The future

Page 53: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Can we fix the problems with push?

Page 54: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Cache digests

Page 55: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Client CDN/Surrogate/Server

Time

@patrickhamann

GET /index.html

CACHE_DIGEST

PUSH_PROMISE main.css

main.css

/index.html

Page 56: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

index.html

main.css

app.js

font.woff

Time

(from disk cache)

(from disk cache)

(from disk cache)

Repeat view

First view

index.html

main.css

app.js

font.woff

Time

Page 57: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

index.html

main.css

app.js

font.woff

Time

(from disk cache)

(from disk cache)

(from disk cache)

Repeat view

First view

index.html

main.css

app.js

font.woff

Time

😎

Page 58: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

IETF Draft Cache Digests for HTTP/2 - K. Oku, Y. Weiss https://tools.ietf.org/html/draft-ietf-httpbis-cache-digest-04

Page 59: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

This still seems too complicated…

Page 60: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

103 Early hints

Page 61: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

The 103 (Early Hints) informational status code indicates to the client that the server is likely to send a final response with the header fields included in the informational response.

Page 62: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Client CDN/Surrogate/Server Origin

Time

GET /index.htmlGET /index.html

/index.html

Server think time

Link: <main.css>; rel=prel

oad 103

GET /main.css

/index.html200

main.css

Page 63: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

1 HTTP/1.1 103 Early Hints 2 Link: </style.css>; rel=preload; as=style 3 Link: </main.js>; rel=preload; as=script 4 Link: </application-data.json>; rel=preload; as=fetch 5 6 HTTP/1.1 200 OK 7 Date: Sun, 03 June 2018 14:40:00 CET 8 Content-length: 1234 9 Content-type: text/html; charset=utf-8 10 Link: </main.css>; rel=preload; as=style 11 Link: </newstyle.css>; rel=preload; as=style 12 Link: </main.js>; rel=preload; as=script

Page 64: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

IETF RFC8297 Early Hints - K. Oku https://tools.ietf.org/html/rfc8297

Page 65: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

103 Early hints:

✅ Same benefits as push

✅ Much simpler

✅ Leverages the browser caches

✅ Allows client to initiate fetches

Page 66: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Priority hints

Page 67: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Web performance made easy: Addy Osmani, Ewa Gasperowicz https://youtu.be/Mv-l3-tJgGk

Page 68: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Priority Hints draft - https://github.com/WICG/priority-hints

Page 69: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Closing

Page 70: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

HTTP/2 doesn’t solve everything.

Page 71: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Resource loading is hard.

Page 72: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

@patrickhamann

Performance is for humans. Optimise for user experiences.

Page 73: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Resource priorities checklist:

✅ Identify your critical resources

✅ Preload hidden sub-resources

✅ Preconnect critical third-parties

❌ Avoid pushing with preload

⚠ Use async push with care

🚀 Decorate HTML with priority hints

🚀 Use Early Hints when available

Page 74: To push or not to push - JSConf › pdf › deck-16372c4610518210.pdfTo push, or not to push?! A journey of resource loading in the browser JSConf EU, June 2018 Patrick Hamann @patrickhamann

Danke

Patrick Hamann speakerdeck.com/patrickhamann

[email protected] @patrickhamann