Slide 1

Slide 1 text

CSS and the: First meaningful paint CSS Conf EU, May 2017 Patrick Hamann @patrickhamann

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

Why?

Slide 4

Slide 4 text

CSS and the first meaningful paint @patrickhamann How do you measure your performance?

Slide 5

Slide 5 text

CSS and the first meaningful paint • First byte • Document complete • Load event • Requests / bytes • Start render • SpeedIndex • First meaningful paint • Time to Interactivity • Custom… Old New

Slide 6

Slide 6 text

CSS and the first meaningful paint @patrickhamann WTF is TTFMP ?

Slide 7

Slide 7 text

CSS and the first meaningful paint @patrickhamann First Meaningful Paint is the time when a page’s primary content appeared on the screen.

Slide 8

Slide 8 text

CSS and the first meaningful paint @patrickhamann First Meaningful Paint is the first paint after which the biggest above-the-fold layout change has happened, and web fonts have loaded.

Slide 9

Slide 9 text

https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI # of layout objects Timeline

Slide 10

Slide 10 text

CSS and the first meaningful paint @patrickhamann A bold statement

Slide 11

Slide 11 text

CSS and the first meaningful paint @patrickhamann A bold statement

Slide 12

Slide 12 text

https://developers.google.com/web/tools/lighthouse/

Slide 13

Slide 13 text

Optimising for TTFMP A case-study: FT.com

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

https://www.webpagetest.org/ Test on real devices Real network conditions

Slide 16

Slide 16 text

CSS and the first meaningful paint @patrickhamann • Where are your users based? • What is their device landscape? • In what context are they using your site? • What is their network profile? • What did they come for? What is your average user profile?

Slide 17

Slide 17 text

CSS and the first meaningful paint @patrickhamann Forming a TTFMP baseline: 3G EM 3G Cable 3 secs 2 secs 1 secs Time to First Meaningful Paint: 3G EM 3G Cable ? ? ? Insert your custom profiles here:

Slide 18

Slide 18 text

Baseline

Slide 19

Slide 19 text

CSS and the first meaningful paint @patrickhamann 1 2 3 4 5 FT.com 6 7 8 9 Other head elements... 10 11 12 13 14 Content ... 15 16 17

Slide 20

Slide 20 text

CSS and the first meaningful paint @patrickhamann

Slide 21

Slide 21 text

Name of Presentation Baseline results TTFMP (ms) 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 Baseline 3G EM 3G Cable

Slide 22

Slide 22 text

Inline critical CSS

Slide 23

Slide 23 text

CSS and the first meaningful paint @patrickhamann Request page Network Renderer GET html Build DOM response Build CSSOM Render page GET css GET js response response idle idle Render blocking Run JS Async JS

Slide 24

Slide 24 text

CSS and the first meaningful paint @patrickhamann Request page Network Renderer GET html Build DOM response Build CSSOM Render page GET css GET js response response idle idle Render blocking Run JS Async JS

Slide 25

Slide 25 text

CSS and the first meaningful paint @patrickhamann Request page Network Renderer GET html Build DOM response Build CSSOM Render page GET css GET js response response idle idle Render blocking Run JS Async JS GET css response

Slide 26

Slide 26 text

CSS and the first meaningful paint @patrickhamann Request page Network Renderer GET html Build DOM response Build CSSOM Render page GET css response idle Async CSS Render

Slide 27

Slide 27 text

ç https://github.com/filamentgroup/loadCSS 1 2 3 4 5 FT.com 6 7 8 html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a{background-color:tran 9 10 Critical styles ... 11 12 13 14 15 16 /*! loadCSS. [c]2017 Filament Group, Inc. MIT License */ 17 (function(){ ... }()); 18 19 20 Other head elements... 21 22 23 24

Slide 28

Slide 28 text

Before

Slide 29

Slide 29 text

Before

Slide 30

Slide 30 text

After

Slide 31

Slide 31 text

After

Slide 32

Slide 32 text

Name of Presentation Inline critical CSS results TTFMP (ms) 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 Baseline Inline 3G EM 3G Cable % Improvement 0 10 20 30 40 50 60 70 80 90 100 TTFMP % impovement 3G EM 3259 63 3G 1462 63 Cable 1327 46

Slide 33

Slide 33 text

CSS and the first meaningful paint • No blocking resources • No SPOF on CSS • Eliminates critical request • Instant painting • Causes reflow • Not cachable • Hard to maintain • Hard to automate Pros Cons

Slide 34

Slide 34 text

Preload

Slide 35

Slide 35 text

CSS and the first meaningful paint @patrickhamann What are your critical resources?

Slide 36

Slide 36 text

Logo? Fonts? Hero image?

Slide 37

Slide 37 text

Lighthouse https://developers.google.com/web/tools/lighthouse/

Slide 38

Slide 38 text

Before

Slide 39

Slide 39 text

CSS and the first meaningful paint @patrickhamann Request page Network Renderer GET html Build DOM response Build CSSOM First paint GET css response idle idle Render blocking Render tree

Slide 40

Slide 40 text

CSS and the first meaningful paint @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

Slide 41

Slide 41 text

CSS and the first meaningful paint @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

Slide 42

Slide 42 text

Preload, W3C working draft https://www.w3.org/TR/preload/

Slide 43

Slide 43 text

CSS and the first meaningful paint @patrickhamann Provides a declarative fetch primitive that initiates an early fetch and separates fetching from resource execution.

Slide 44

Slide 44 text

CSS and the first meaningful paint @patrickhamann 1 2 3 4 5 6 var res = document.createElement("link"); 7 res.rel = "preload"; 8 res.as = "style"; 9 res.href = "styles/other.css"; 10 document.head.appendChild(res); 11 1 Link: rel=“preload”; as=“style” nopush Preload with markup: Preload with HTTP header:

Slide 45

Slide 45 text

CSS and the first meaningful paint @patrickhamann < GET /index.html
 
 < HTTP/1.1 200 OK < Cache-Control: private, max-age=60, must-revalidate < Expires: Thu, 20 Apr 2017 21:39:52 GMT < Last-Modified: Thu, 20 Apr 2017 13:11:33 GMT < ETag: "966eca3815d88d8848933d33c68ab2bd" < Content-Type: text/html < Content-Encoding: gzip < Content-Length: 43177 < Date: Thu, 20 Apr 2017 21:39:52 GMT < Connection: keep-alive < Link: ; as=style; rel=preload; nopush, 
 ; rel=preload as=font crossorigin nopush, ; rel=preload as=font crossorigin nopush, ; as=image; rel=preload; nopush

Slide 46

Slide 46 text

Before

Slide 47

Slide 47 text

After

Slide 48

Slide 48 text

Name of Presentation Preload results TTFMP (ms) 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 Baseline Inline Preload 3G EM 3G Cable % Improvement 0 10 20 30 40 50 60 70 80 90 100 TTFMP % impovement 3G EM 3176 64 3G 1778 55 Cable 1042 57

Slide 49

Slide 49 text

CSS and the first meaningful paint • Indicate hidden resources • Dictate priority and order • Separates fetch from exec • Easy to create contention • Requires server logic Pros Cons

Slide 50

Slide 50 text

Server push

Slide 51

Slide 51 text

CSS and the first meaningful paint @patrickhamann HTTP/2

Slide 52

Slide 52 text

CSS and the first meaningful paint @patrickhamann ! " Client Server GET /index.html GET /main.css 200 OK /index.html #

Slide 53

Slide 53 text

CSS and the first meaningful paint @patrickhamann ! " Client Server PUSH_PROMISE /main.css 200 OK /index.html GET /index.html

Slide 54

Slide 54 text

CSS and the first meaningful paint @patrickhamann 1 2 3 4 5 FT.com 6 7 8 9 ... 10 1 Link: ; rel=“preload”; as=“style” Indicate push of critical styles with Link preload header: Convert inline styles into normal link rel=“stylesheet” declaration and async the main styles

Slide 55

Slide 55 text

Before index.html main.css Start render TTFMP Idle Idle

Slide 56

Slide 56 text

TTFMP Start render After critical.css TTFMP index.html main.css Idle Start render Idle

Slide 57

Slide 57 text

CSS and the first meaningful paint @patrickhamann /hero.jpg Stream ID: 4 Weight: 16 /data.json Stream ID: 7 Weight: 16 /app.js Stream ID: 3 Weight: 64 /icon.svg Stream ID: 9 Weight: 16 /main.css Stream ID: 2 Weight: 110 /index.html Stream ID: 1 Weight: 128

Slide 58

Slide 58 text

Result

Slide 59

Slide 59 text

Name of Presentation Push results TTFMP (ms) 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 Baseline Inline Preload Push 1256 1042 1327 2477 2826 1778 1462 3983 5035 3176 3259 8849 3G EM 3G Cable % Improvement 0 10 20 30 40 50 60 70 80 90 100 TTFMP % impovement 3G EM 5035 43 3G 2826 29 Cable 1256 49

Slide 60

Slide 60 text

CSS and the first meaningful paint @patrickhamann Is indicating push via the HTML response too late?

Slide 61

Slide 61 text

Async push

Slide 62

Slide 62 text

TTFMP Start render After critical.css TTFMP index.html main.css Idle Start render Idle

Slide 63

Slide 63 text

CSS and the first meaningful paint @patrickhamann ! " Client Server PUSH_PROMISE /main.css - # 200 OK /index.html GET /index.html ! GET /index.html 200 OK /index.html App

Slide 64

Slide 64 text

CSS and the first meaningful paint @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);

Slide 65

Slide 65 text

After

Slide 66

Slide 66 text

Name of Presentation Push async results TTFMP (ms) 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 Baseline Inline Preload Push Push async 3G EM 3G Cable % Improvement 0 10 20 30 40 50 60 70 80 90 100 TTFMP % impovement 3G EM 3062 65 3G 1613 59 Cable 1021 58

Slide 67

Slide 67 text

CSS and the first meaningful paint • Uses idle time • Ensures delivery before preload • Easy to create contention • Limited avaliablity • Custom server logic • Hard to debug Pros Cons

Slide 68

Slide 68 text

CSS and the first meaningful paint @patrickhamann What about the repeat view?

Slide 69

Slide 69 text

CSS and the first meaningful paint @patrickhamann PRPL

Slide 70

Slide 70 text

Result

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

The future

Slide 73

Slide 73 text

103 Early hints status code for HTTP, K. Oku https://tools.ietf.org/html/draft-ietf-httpbis-early-hints-01

Slide 74

Slide 74 text

Cache digests for HTTP/2, K. Oku https://tools.ietf.org/html/draft-ietf-httpbis-cache-digest-01

Slide 75

Slide 75 text

Conclusion

Slide 76

Slide 76 text

CSS and the first meaningful paint @patrickhamann Resource loading is hard.

Slide 77

Slide 77 text

CSS and the first meaningful paint @patrickhamann Bandwidth is often 
 under-utilised

Slide 78

Slide 78 text

CSS and the first meaningful paint @patrickhamann Identify your critical resources and request chains.

Slide 79

Slide 79 text

CSS and the first meaningful paint @patrickhamann Use preload to indicate critical resources, such as fonts to the browser.

Slide 80

Slide 80 text

CSS and the first meaningful paint @patrickhamann Push critical CSS, but only on first view and only within idle time.

Slide 81

Slide 81 text

CSS and the first meaningful paint @patrickhamann Always be testing.

Slide 82

Slide 82 text

Thanks! Patrick Hamann [email protected] @patrickhamann