Slide 1

Slide 1 text

Name of Presentation CSS and the: First meaningful paint All Day Hey, April 2017
 Patrick Hamann @patrickhamann

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

Name of Presentation Why?

Slide 4

Slide 4 text

CSS and the first meaningful paint @patrickhamann How fast is your website?

Slide 5

Slide 5 text

CSS and the first meaningful paint @patrickhamann What is the golden performance metric?

Slide 6

Slide 6 text

CSS and the first meaningful paint @patrickhamann Does it even exist… Should it even exist?

Slide 7

Slide 7 text

CSS and the first meaningful paint @patrickhamann How can we measure the perception and experience of our real users?

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 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 11

Slide 11 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 12

Slide 12 text

CSS and the first meaningful paint @patrickhamann A bold statement

Slide 13

Slide 13 text

https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI

Slide 14

Slide 14 text

# of layout objects Timeline

Slide 15

Slide 15 text

CSS and the first meaningful paint @patrickhamann A bold statement

Slide 16

Slide 16 text

CSS and the first meaningful paint @patrickhamann A bold statement

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Name of Presentation Optimising for TTFMP A case-study: FT.com

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

CSS and the first meaningful paint @patrickhamann • Where are your users based? • What is your 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 22

Slide 22 text

CSS and the first meaningful paint @patrickhamann The average load time for mobile sites is 19 seconds over 3G connections The need for mobile speed, Google DoubleClick

Slide 23

Slide 23 text

CSS and the first meaningful paint @patrickhamann 53% of mobile site visits are abandoned if pages takes longer than 3 seconds to load. The need for mobile speed, Google DoubleClick

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 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 26

Slide 26 text

CSS and the first meaningful paint @patrickhamann Case-study profile: BW down BW up Latency RTT 3G EM 400 kbs 400 kbs 400 ms 3G 1.6 Mbs 768 kbs 150 ms Cable 5m Mbs 1Mbs 28 ms • Moto G (low-mid Android) • 9 runs • Chrome beta

Slide 27

Slide 27 text

Name of Presentation Baseline

Slide 28

Slide 28 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 29

Slide 29 text

CSS and the first meaningful paint @patrickhamann

Slide 30

Slide 30 text

Name of Presentation Baseline results TTFMP (ms) 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 Baseline 3G EM 3G Cable TTFMP % impovement 3G EM 3259 63 3G 1462 63 Cable 1327 46

Slide 31

Slide 31 text

Name of Presentation Inline critical CSS

Slide 32

Slide 32 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

Slide 33

Slide 33 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

Slide 34

Slide 34 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 GET css response

Slide 35

Slide 35 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 Render

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

! !

Slide 38

Slide 38 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 39

Slide 39 text

TCP slow-start https://hpbn.co/building-blocks-of-tcp/

Slide 40

Slide 40 text

Before

Slide 41

Slide 41 text

After

Slide 42

Slide 42 text

After

Slide 43

Slide 43 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 44

Slide 44 text

CSS and the first meaningful paint • No blocking resources • No SPOF on CSS • Less requests over wire • Instant painting • Causes reflow • Not cachable • Hard to maintain • Hard to automate Pros Cons

Slide 45

Slide 45 text

Name of Presentation Preload

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

Logo? Fonts? Hero image?

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

Before

Slide 51

Slide 51 text

Before

Slide 52

Slide 52 text

CSS and the first meaningful paint @patrickhamann Network JavaScript Render tree Layout Paint HTML DOM CSS CSSOM Network JavaScript Render tree Layout Paint HTML DOM CSS CSSOM

Slide 53

Slide 53 text

CSS and the first meaningful paint @patrickhamann Network JavaScript Render tree Layout Paint HTML CSS CSSOM Network JavaScript Render tree Layout Paint HTML DOM CSS CSSOM

Slide 54

Slide 54 text

CSS and the first meaningful paint @patrickhamann Network JavaScript Render tree Layout Paint HTML CSS CSSOM Network JavaScript Render tree Layout Paint HTML DOM CSS CSSOM

Slide 55

Slide 55 text

CSS and the first meaningful paint @patrickhamann Network JavaScript Render tree Layout Paint CSS CSSOM Network JavaScript Render tree Layout Paint HTML DOM CSS CSSOM

Slide 56

Slide 56 text

CSS and the first meaningful paint @patrickhamann JavaScript Render tree Layout Paint CSSOM Network JavaScript Render tree Layout Paint HTML DOM CSS CSSOM

Slide 57

Slide 57 text

CSS and the first meaningful paint @patrickhamann Render tree Layout Paint Network JavaScript Render tree Layout Paint HTML DOM CSS CSSOM

Slide 58

Slide 58 text

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model

Slide 59

Slide 59 text

CSS and the first meaningful paint @patrickhamann The preload scanner

Slide 60

Slide 60 text

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

Slide 61

Slide 61 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 62

Slide 62 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 63

Slide 63 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 64

Slide 64 text

Before

Slide 65

Slide 65 text

Before

Slide 66

Slide 66 text

After

Slide 67

Slide 67 text

Preload browser support, April 2017, http://caniuse.com/#feat=link-rel-preload

Slide 68

Slide 68 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 69

Slide 69 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 70

Slide 70 text

Name of Presentation Server push

Slide 71

Slide 71 text

CSS and the first meaningful paint @patrickhamann HTTP/2

Slide 72

Slide 72 text

CSS and the first meaningful paint @patrickhamann " # Client Server

Slide 73

Slide 73 text

CSS and the first meaningful paint @patrickhamann " # Client Server GET /index.html

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

CSS and the first meaningful paint @patrickhamann " # Client Server

Slide 77

Slide 77 text

CSS and the first meaningful paint @patrickhamann " # Client Server GET /index.html

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 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 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 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 84

Slide 84 text

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

Slide 85

Slide 85 text

After

Slide 86

Slide 86 text

After

Slide 87

Slide 87 text

HTTP/2 browser support, April 2017, http://caniuse.com/#feat=http2

Slide 88

Slide 88 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 89

Slide 89 text

CSS and the first meaningful paint • Easy to configure • Creates contention • Requires server logic • Hard to debug • Not cache aware Pros Cons

Slide 90

Slide 90 text

Name of Presentation Asynchronous Push

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

CSS and the first meaningful paint @patrickhamann " # Client Server HTTP/2 connection

Slide 94

Slide 94 text

CSS and the first meaningful paint @patrickhamann " # Client Server HTTP/2 connection GET /index.html

Slide 95

Slide 95 text

CSS and the first meaningful paint @patrickhamann " # Client Server PUSH_PROMISE /main.css $ HTTP/2 connection GET /index.html

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

CSS and the first meaningful paint @patrickhamann " # Client Server " App

Slide 98

Slide 98 text

CSS and the first meaningful paint @patrickhamann " # Client Server GET /index.html " GET /index.html App

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 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 102

Slide 102 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 103

Slide 103 text

Before

Slide 104

Slide 104 text

After

Slide 105

Slide 105 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 106

Slide 106 text

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

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text

Name of Presentation Results

Slide 109

Slide 109 text

No content

Slide 110

Slide 110 text

No content

Slide 111

Slide 111 text

No content

Slide 112

Slide 112 text

No content

Slide 113

Slide 113 text

Name of Presentation The future

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

https://www.ietf.org/proceedings/95/slides/slides-95-httpbis-5.pdf

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

https://www.ietf.org/proceedings/97/slides/slides-97-httpbis-sessb-early-hints-00.pdf

Slide 118

Slide 118 text

Name of Presentation Conclusion

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

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

Slide 122

Slide 122 text

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

Slide 123

Slide 123 text

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

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

Name of Presentation Thanks! Patrick Hamann [email protected] @patrickhamann