Killer page load performance

53
Killer performance Jonas Ohlsson @pocketjoso BEATING THE COMPETITION

Transcript of Killer page load performance

Page 1: Killer page load performance

Killer performance

Jonas Ohlsson@pocketjoso

BEATING THE COMPETITION

Page 2: Killer page load performance

Jonas Ohlsson

Front end developer at State

Perf and tooling geek

Author of Penthouse

https://github.com/pocketjoso/penthouse/

Page 3: Killer page load performance
Jonas
The problem
Page 4: Killer page load performance

10 seconds later

LET’S GO SOMEWHERE ELSE..

Page 5: Killer page load performance

https://www.facebook.com/instantArticles

Page 6: Killer page load performance

Is the Web slow?

Jonas
Too slow?vs Native
Page 7: Killer page load performance

http://www.quirksmode.org/blog/archives/2015/05/web_vs_native_l.html

Page 8: Killer page load performance
Page 9: Killer page load performance

Are heavy JS frameworks responsible for the slow

web?

Page 10: Killer page load performance

Page LoadKEY CONCEPTS

Page 11: Killer page load performance

Perceived load

PAGE LOAD KEY CONCEPTS

Page 12: Killer page load performance
Jonas
What happens behind the scenes..
Page 13: Killer page load performance

Start Render

Total Page Load Time

PAGE LOAD KEY CONCEPTS

Page 14: Killer page load performance

http://webpagetest.org

Jonas
TimelapseFonts
Page 15: Killer page load performance

SpeedIndex

PAGE LOAD KEY CONCEPTS

Jonas
Quantitative, automate
Page 16: Killer page load performance

1 second to“break the glass”

PAGE LOAD KEY CONCEPTS

https://developers.google.com/speed/docs/insights/mobile

Jonas
What we’re aiming forTrain of though
Page 17: Killer page load performance

(Request) Latency kills mobile performance

https://developers.google.com/speed/docs/insights/mobile

PAGE LOAD KEY CONCEPTS

Jonas
Today: 200ms avg roundtrip time
Page 18: Killer page load performance

Page LoadSTATS

#perfmatters

https://twitter.com/hashtag/perfmatters

Page 19: Killer page load performance

http://www.webperformancetoday.com/2012/02/28/4-awesome-slides-showing-how-page-speed-correlates-to-business-metrics-at-walmart-com/

PAGE LOAD STATS

Page 20: Killer page load performance

http://kylerush.net/blog/meet-the-obama-campaigns-250-million-fundraising-platform/

PAGE LOAD STATS

Page 21: Killer page load performance

https://blog.mozilla.org/metrics/2010/04/05/firefox-page-load-speed-%E2%80%93-part-ii/

PAGE LOAD STATS

Page 22: Killer page load performance

Page LoadTOOLS

Page 23: Killer page load performance

https://developers.google.com/speed/pagespeed/insights/

PAGE LOAD TOOLS

Page 24: Killer page load performance

https://developers.google.com/speed/pagespeed/insights/

PAGE LOAD TOOLS

Page 25: Killer page load performance

http://webpagetest.org

PAGE LOAD TOOLS

Jonas
TimelapseFonts
Page 26: Killer page load performance

WebPageTest CLI / Node module

https://github.com/marcelduran/webpagetest-api

Perf budget (grunt)

https://github.com/tkadlec/grunt-perfbudget

PAGE LOAD TOOLS

Page 27: Killer page load performance

http://timkadlec.com/2015/05/choosing-performance/

Jonas
Why still a problem?Culture
Page 28: Killer page load performance

http://www.filamentgroup.com/lab/weight-wait.html

Jonas
Why still a problem?Lack of understanding of solution
Page 29: Killer page load performance

http://www.filamentgroup.com/lab/weight-wait.html

Jonas
Same content.Still JS there (jQuery)
Page 30: Killer page load performance

THEORY

Critical Path for rendering

Jonas
Who knows already?
Page 31: Killer page load performance

HTML

<html><head><script src=‘bundle.js’></script><link rel=‘style’

href=‘styles.css’></link></head><body>…

</body></html>

CSS

JS

Start render

CRITICAL PATH FOR RENDERING

Page 32: Killer page load performance

<html><head><link rel=‘style’

href=‘styles.css’></link></head><body>…<script src=‘bundle.js’></script>

</body></html>

Start render

HTMLCSS

JS

CRITICAL PATH FOR RENDERING

Page 33: Killer page load performance

<html><head></head><body>…<script src=‘bundle.js’></script><link rel=‘style’

href=‘styles.css’></link></body></html>

Start render

HTMLCSS

JS

CRITICAL PATH FOR RENDERING

Page 34: Killer page load performance
Page 35: Killer page load performance

<html><head><style>/* critical styles for page*/

</style></head><body>…<script src=‘bundle.js’></script><link rel=‘style’

href=‘styles.css’></link></body></html>

Start render

HTMLCSS

JS

CRITICAL PATH FOR RENDERING

Page 36: Killer page load performance

<html><head><style>/* critical styles for page*/

</style><script src=‘bundle.js’

async></script>

</head><body>…<link rel=‘style’

href=‘styles.css’></link></body></html>

Start render

HTMLCSS

JS

CRITICAL PATH FOR RENDERING

Page 37: Killer page load performance

<html><head><style>/* critical styles for page*/

</style><script>function loadCss()…loadCss(‘styles.css’);</script><script src=‘bundle.js’

async></script>

</head><body>…

</body></html>

Start render

HTMLCSS

JS

CRITICAL PATH FOR RENDERING

https://github.com/filamentgroup/loadCSS

Page 38: Killer page load performance

TCP slow start

First roundtrip only fits ~14kb

Jonas
TCP estimates connection capacity therefor cannot immediately use the full available bandwidth
Page 39: Killer page load performance

Styles needed to render immediately visible content

~ “above the fold”

Per page

Critical Path CSS

https://github.com/addyosmani/critical/

Page 40: Killer page load performance

Critical path css generators

Manually

http://jonassebastianohlsson.com/criticalpathcssgenerator

Static content

https://github.com/addyosmani/critical

CLI or build process (node, gulp, grunt)

https://github.com/pocketjoso/penthouse

Page 41: Killer page load performance

Automating Critical Css

Page 42: Killer page load performance

AUTOMATING CRITICAL CSS

grunt-penthouse

penthouse: {home : {

css : ‘styles/fullCss.css’,url : ‘localhost:8000/’,outfile : 'index.html.css',width : 1300, height : 900

}}

Page 43: Killer page load performance

AUTOMATING CRITICAL CSS

grunt-penthousepenthouse: {

home : {css : ‘styles/fullCss.css’,url : ‘localhost:8000/’,outfile : 'index.html.css',width : 1300, height : 900

},work : {

css : ‘styles/fullCss.css’,url : ‘localhost:8000/work/’,outfile : 'work/index.html.css',width : 1300, height : 900

}, ..

Page 44: Killer page load performance

AUTOMATING CRITICAL CSS

Rewrite relative paths

<link rel=‘style’ href=‘css/styles.css’></link>

// cssurl: (‘../fonts/Lato.woff’)

// inline in <head><style>url: (‘fonts/Lato.woff’)

</style>

Page 45: Killer page load performance

AUTOMATING CRITICAL CSS

penthouse (Node)[ ‘localhost:8000/’, ‘localhost:8000/work/’].map(function(url){ penthouse({

css : ‘styles/fullCss.css’, url : url, width : 1300, height : 900 }, function(err, criticalCss) {if (err) return;

fs.writeFile(someFileName, criticalCss); });});

Page 46: Killer page load performance

AUTOMATING CRITICAL CSS

Using local files[ ‘index.html’, // will be rendered over file protocol ‘work/index.html’].map(function(url){ penthouse({

css : ‘styles/fullCss.css’, url : url, width : 1300, height : 900 }, function(err, criticalCss) {if (err) return;

fs.writeFile(someFileName, criticalCss); });});

Page 47: Killer page load performance

AUTOMATING CRITICAL CSS

Serving critical css

<head>{{#if criticalCss}} <style>{{{ criticalCss }}}</style> <script> function loadCSS(){…} loadCSS(‘{{ stylesUrl }}’); </script> {{else}} <link rel='stylesheet'

href='{{ stylesUrl }}' /> {{/if}}</head>

Page 48: Killer page load performance

AUTOMATING CRITICAL CSS

Serving critical css<head>{{#if criticalCss}} <style>{{{ criticalCss }}}</style> <script> function loadCSS(){…} loadCSS(‘{{ stylesUrl }}’); </script> <noscript><link rel='stylesheet'

href='{{ stylesUrl }}' /></noscript> {{else}} <link rel='stylesheet'

href='{{ stylesUrl }}' /> {{/if}}</head>

Page 49: Killer page load performance

Flash Of Invisible Text

Jonas
@font-face
Page 50: Killer page load performance

var ffObserver = new FontFaceObserver('Lato Web', { weight: 400});var ffBoldObserver = new FontFaceObserver('Lato Web', { weight: 700});

window.Promise.all([ ffObserver.check(), ffBoldObserver.check()]).then(function(){

document.documentElement.className +=

‘ fonts-loaded’;});

FLASH OF INVISIBLE TEXT FIX

FontFaceObserver

https://github.com/bramstein/fontfaceobserver

Page 51: Killer page load performance

body { font-family: sans-serif;};

.fonts-loaded body {font-family: ‘Lato Web’, sans-serif;}

FLASH OF INVISIBLE TEXT FIX

FontFaceObserver

https://github.com/bramstein/fontfaceobserver

Page 52: Killer page load performance

FLASH OF INVISIBLE TEXT FIX

Jonas
@font-face
Page 53: Killer page load performance

Questions?

Jonas Ohlsson@pocketjoso

BOOM!