to push or not to push
play

To push, or not to push?! A journey of resource loading in the - PowerPoint PPT Presentation

To push, or not to push?! A journey of resource loading in the browser Fluent Conference, June 2018 Patrick Hamann @patrickhamann Why? HTTP/2 will solve this Everybody @patrickhamann Resource loading in the browser is hard.


  1. To push, or not to push?! A journey of resource loading in the browser Fluent Conference, June 2018 Patrick Hamann @patrickhamann

  2. Why?

  3. “HTTP/2 will solve this” – Everybody @patrickhamann

  4. Resource loading in the browser is hard. @patrickhamann

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

  6. How can we load our resources most efficiently? @patrickhamann

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

  8. What are my critical resources? ✅ Critical CSS for current route ✅ Fonts ✅ Hero images ✅ Initial application route 
 ✅ Application bootstrap data

  9. First Contentful Paint Time to Interactive First Meaningful Paint Fully loaded User navigates

  10. First Contentful Paint Time to Interactive First Meaningful Paint Fully loaded User navigates

  11. A good loading strategy: ✅ Prioritises above-the-fold rendering ✅ Prioritises interactivity ✅ Is easy to use ✅ Is measurable

  12. Preload

  13. Renderer Request page idle Build DOM idle Build CSSOM Render tree First paint Text paint Network GET html response 😣 Render blocking GET css response Text blocking GET font response @patrickhamann

  14. What are my hidden sub-resources? ✅ Fonts ✅ Application data ✅ Application routes ✅ Async third parties

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

  16. Preload with HTTP header: 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: 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> @patrickhamann

  17. Before

  18. After

  19. 
 “ 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 @patrickhamann

  20. Preconnect

  21. No preconnect Time index.html main.css app.js font.woff Time index.html main.css app.js font.woff Preconnect

  22. Are indicating resource hints via the HTML response too late? @patrickhamann

  23. Server push

  24. Client CDN/Surrogate/Server Origin GET /index.html Time GET /index.html Server think time 😣 /index.html 0 0 2 /index.html 0 0 2 GET main.css GET /main.css @patrickhamann

  25. Jake Archibald – https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/

  26. Stream Message A virtual channel within an established connection which A complete sequence of frames that map to a logical HTTP carries bidirectional messages. message, such as a request. Connection Stream Message Frame :method: GET � � :path: /image-2.jpg Frame Frame :status 200 Server Client :version: HTTP/2.0 … response payload :vary: Accept-Encoding Frame Multiplexing The smallest unit of communication, which carries a specific type of data—e.g., HTTP headers, payload, commands e.t.c. @patrickhamann

  27. Client CDN/Surrogate/Server Origin GET /index.html Time GET /index.html Server think time /index.html 0 0 2 d a o l e r p = l e r ; > s s c . n i a m < : k n i L PUSH_PROMISE s s c . n i a m /index.html main.css @patrickhamann

  28. So how can I push? @patrickhamann

  29. Indicate push via preload Link header. 1 Link: <font.woff2>; rel=preload; as=font crossorigin h s u p e b l a s d i o t e t u b r i t t a h s u p o n e s U d . a o e l r p e s u y l n o d n a s c i t n a m e s 1 Link: <main.css>; rel=preload; as=style; nopush F a s t l y u s e s x - h t t p 2 - p u s h - o n l y a t t r i b u t e t o d i s a b l e p r e l o a d s e m a n t i c s 1 Link: <application.js>; rel=preload; as=style; x-http2-push-only @patrickhamann

  30. Time index.html main.css app.js font.woff Before

  31. Time index.html main.css app.js font.woff After

  32. No Push Time index.html main.css app.js 1 RTT saving! font.woff Time index.html main.css app.js font.woff Push

  33. Time index.html Idle main.css 😣 app.js font.woff After

  34. Client CDN/Surrogate/Server Origin GET /index.html Time GET /index.html Server think time 😣 /index.html 0 0 2 d a o l e r p = l e r ; > s s c . n i a m < : k n i L PUSH_PROMISE s s c . n i a m /index.html main.css @patrickhamann

  35. Server push benefits: ✅ 1 RTT saving ✅ Useful for long server think time ✅ Useful for long RTT times ⚠ Link header indication is too late

  36. Is indicating push via the HTML response too late? @patrickhamann

  37. Async push

  38. Client CDN/Surrogate/Server Origin GET /index.html Time GET /index.html PUSH_PROMISE Server think time s s c . n i a m main.css 😏 /index.html 0 0 2 /index.html @patrickhamann

  39. 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); @patrickhamann

  40. 1 sub vcl_recv { 2 if (fastly_info.is_h2 && req.url ~ "^/index.html") { 3 h2.push('/critical.css'); 4 } 5 6 // etc ... 7 8 } @patrickhamann

  41. Push Time index.html main.css app.js font.woff Time index.html main.css app.js font.woff Async push

  42. Time index.html main.css 😏 app.js font.woff Utilising idle network server think time == win!

  43. What about the repeat view? @patrickhamann

  44. First view Time index.html main.css app.js font.woff Time index.html main.css (from disk cache) app.js font.woff (from disk cache) Repeat view

  45. The server has no knowledge of client cache state. @patrickhamann

  46. In the wild

  47. 
 “ Faster image loads times, 
 15% reduction in time to first byte – Facebook @patrickhamann

  48. HTTP2 server push - Facebook https://atscaleconference.com/videos/http2-server-push-lower-latencies-around-the-world/

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

  50. Poll? @patrickhamann

  51. So what’s the problem?

  52. Client CDN/Surrogate/Server GET /index.html Time PUSH_PROMISE s s c . n i a m main.css RST_STREAM m a i n . c s s @patrickhamann

  53. Client CDN/Surrogate/Server GET /index.html Time PUSH_PROMISE s s c . n i a m main.css RST_STREAM m a i n . c s s @patrickhamann

  54. r e p e h c a c h s u p e a t r a p e S . n o i t c e n n o c 2 / P T T H Memory cache Push cache Page Service Worker HTTP cache Server Memory cache Push cache Page @patrickhamann

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

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

  57. ✅ ✅ ⚠ ⚠ HTTP/2 Server Push - Browser inconsistencies

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

  59. 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 cache (SW, native, Electron etc)

  60. Is the 1 RTT saving worth the complexity? @patrickhamann

  61. Are there other solutions? @patrickhamann

  62. The future

  63. Can we fix the problems with push? @patrickhamann

  64. Cache digests

  65. Client CDN/Surrogate/Server GET /index.html Time CACHE_DIGEST PUSH_PROMISE s s c . n i a m main.css /index.html @patrickhamann

  66. Time index.html main.css app.js font.woff First view Time index.html (from disk cache) main.css (from disk cache) app.js font.woff (from disk cache) Repeat view

Recommend


More recommend