Pro Yearly is on sale from $80 to $50! »

WordCamp Ubud: Performance - Moving to HTTP2

WordCamp Ubud: Performance - Moving to HTTP2

1dd9fded718f9b344d48f37f9bfcb159?s=128

Peter Wilson

April 23, 2017
Tweet

Transcript

  1. Wed 29 Oct 1969 ~ ucla$ ░

  2. Wed 29 Oct 1969 ~ ucla$ ░

  3. Wed 29 Oct 1969 ~ ucla$

  4. Wed 29 Oct 1969 ~ ucla$ lo ░ gin

  5. Wed 29 Oct 1969 ~ ucla$ lo ░ ░

  6. Seven times faster: 
 a study in front-end optimisation Peter

    Wilson • peterwilson.cc • @pwcc
  7. None
  8. WordPress is slow

  9. Front-end code is slow

  10. Bytes on the page

  11. Total page size (MB) Nov 2011 - April 2017 0.5

    1.0 1.5 2.0 2.5 3.0 1 Nov '11 1 Jul '12 1 Mar '13 1 Nov '13 1 Jul '14 1 Mar '15 1 Nov '15 1 Jul '16 1 Mar '17 httparchive.org/trends.php, April 2017
  12. Assets per page Nov 2011 - April 2017 20 40

    60 80 100 120 140 1 Nov '1115 May '121 Dec '1215 Jun '13 1 Jan '14 15 Jul '14 1 Feb '1515 Aug '151 Mar '1615 Sep '16 1 Apr '17 httparchive.org/trends.php, March 2017
  13. Webfonts Multiple of Nov 2011 (bytes) 2 4 6 8

    10 12 14 16 18 1 Nov '11 15 May '12 1 Dec '12 15 Jun '13 1 Jan '14 15 Jul '14 1 Feb '15 15 Aug '15 1 Mar '16 httparchive.org/trends.php, March 2016
  14. Load time httparchive.org/trends.php, March 2016

  15. Load time httparchive.org/trends.php, March 2016

  16. Load time Start render Visually complete 15.23 seconds

  17. Two seconds

  18. Walmart conversion rate slideshare.net/devonauerswald/walmart-pagespeedslide 0 - 1 1 - 2

    2 - 3 3 - 4 4 - 5 5 - 6 6 - 7 7 - 8 8 - 9 9 - 10 10 - 11 11 - 12 12 - 13 13 - 14 14 - 15 15+
  19. The average site kills conversions.

  20. Measure a starting point

  21. None
  22. WebPageTest - webpagetest.org

  23. WebPageTest - webpagetest.org

  24. Key metrics Document Complete Fully Loaded Load Time First Byte

    Start Render Speed Index DOM Elements Time Requests Bytes In Time Requests Bytes In 3.770s 0.771s 1.789s 1834 397 3.770s 27 635 KB 4.072s 33 661 KB WebPageTest - webpagetest.org
  25. Timeline view

  26. Comparison timelines Additional blocking request in HTML Header Timed using

    WebPageTest - pwcc.cc/go/blocking 0.5s 1.0s 1.5s 2.0s 0% 0% 0% 100% 0% 86% 100% Blocked Unblocked
  27. Comparison timelines Additional blocking request in HTML Header 0.5s 1.0s

    1.5s 2.0s 0% 0% 0% 100% 0% 86% 100% Blocked Unblocked Timed using WebPageTest - pwcc.cc/wceu/blocking
  28. 53 / 100 Our PageSpeed score is you won’t believe

    how
 much it’s costing
  29. What will get my visitors reading quickest? “ ”

  30. Doing it wrong

  31. JavaScript in the footer

  32. All visitors have JavaScript disabled while it downloads. – Every

    progressive enhancement advocate ever “ ”
  33. wp_enqueue_script( 'pwcc-scripts', // handle '/functions.js', // source null, // no

    dependancies '20160624-26', // version true // load in footer ); JavaScript, the WordPress way
  34. wp_enqueue_script( 'pwcc-scripts', // handle '/functions.js', // source null, // no

    dependancies '20160624-26', // version true // load in footer ); true // load in footer JavaScript, the WordPress way
  35. wp_enqueue_script( 'pwcc-scripts', // handle '/functions.js', // source array( 'jquery' ),

    // jQuery loads automatically '20160624-26', // version true // load in footer ); jQuery, the WordPress way
  36. wp_enqueue_script( 'pwcc-scripts', // handle '/functions.js', // source array( 'jquery' ),

    // jQuery loads automatically '20160624-26', // version true // load in footer ); array( 'jquery' ), // jQuery loads automatically jQuery, the WordPress way
  37. <html> <head> <script src='jquery.js'></script><!--32kB--> <script src='jquery-migrate.js'></script><!--4.4kB--> </head> <body> <!-- Site

    content. --> <script src='/functions.js'></script> jQuery, doing_it_wrong()
  38. <html> <head> <script src='jquery.js'></script><!--32kB--> <script src='jquery-migrate.js'></script><!--4.4kB--> </head> <body> <!-- Site

    content. --> <script src='/functions.js'></script> </body> </html> jQuery, doing_it_wrong()
  39. The WordPress way blocks rendering Daniel Zedda (CC) - flic.kr/p/a6wwAh

  40. function pwcc_jquery_to_footer() { if ( is_admin() ) return; wp_script_add_data( 'jquery',

    'group', 1 ); wp_script_add_data( 'jquery-core', 'group', 1 ); wp_script_add_data( 'jquery-migrate', 'group', 1 ); } add_action( 'wp', 'pwcc_jquery_to_footer' ); jQuery, doing_it_wrong()
  41. function pwcc_jquery_to_footer() { if ( is_admin() ) return; wp_script_add_data( 'jquery',

    'group', 1 ); wp_script_add_data( 'jquery-core', 'group', 1 ); wp_script_add_data( 'jquery-migrate', 'group', 1 ); } add_action( 'wp', 'pwcc_jquery_to_footer' ); wp_script_add_data( 'jquery', 'group', 1 ); wp_script_add_data( 'jquery-core', 'group', 1 ); wp_script_add_data( 'jquery-migrate', 'group', 1 ); jQuery, doing_it_wrong()
  42. function pwcc_jquery_to_footer() { if ( is_admin() ) return; wp_script_add_data( 'jquery',

    'group', 1 ); wp_script_add_data( 'jquery-core', 'group', 1 ); wp_script_add_data( 'jquery-migrate', 'group', 1 ); } add_action( 'wp', 'pwcc_jquery_to_footer' ); wp_script_add_data( 'jquery', 'group', 1 ); wp_script_add_data( 'jquery-core', 'group', 1 ); wp_script_add_data( 'jquery-migrate', 'group', 1 ); jQuery, doing_it_wrong()
  43. <html> <head> <script src='jquery.js'></script><!--32kB--> <script src='jquery-migrate.js'></script><!--4.4kB--> </head> <body> <!-- Site

    content. --> <script src='/functions.js'></script> jQuery, the WordPress way
  44. <html> <head> <!-- HTML Header. --> </head> <body> <!-- Site

    content. --> <script src='jquery.js'></script><!--32kB--> <script src='jquery-migrate.js'></script><!--4.4kB--> <script src='/functions.js'></script> </body> jQuery, doing_it_wrong()
  45. <html> <head> <!-- HTML Header. --> </head> <body> <!-- Site

    content. --> <script src='jquery.js'></script><!--32kB--> <script src='jquery-migrate.js'></script><!--4.4kB--> <script src='/functions.js'></script> </body> </html> jQuery, doing_it_wrong() pwcc.cc/go/jqueryfooter
  46. None
  47. Asynchronous JavaScript

  48. Asynchronous JavaScript <script type='text/javascript' src='/path/file.js' async></script>

  49. Asynchronous JavaScript <script type='text/javascript' src='/path/file.js' async></script> async

  50. function pwcc_async_js( $tag, $handle ) { switch ( $handle )

    { case 'pwcc-scripts' : $tag = str_replace( '></script', ' async></script', $tag ); } return $tag; } Asynchronous JavaScript
  51. function pwcc_async_js( $tag, $handle ) { switch ( $handle )

    { case 'pwcc-scripts' : // Falls through case 'picturefill' : $tag = str_replace( '></script', ' async></script', $tag ); } return $tag; } Asynchronous JavaScript
  52. function pwcc_async_js( $tag, $handle ) { switch ( $handle )

    { case 'pwcc-scripts' : // Falls through case 'picturefill' : $tag = str_replace( '></script', ' async></script', $tag ); } return $tag; } Asynchronous JavaScript
  53. switch ( $handle ) { case 'pwcc-scripts' : // Falls

    through case 'picturefill' : $tag = str_replace( '></script', ' async></script', $tag ); } return $tag; } add_filter( 'script_loader_tag', 'pwcc_async_js', 10, 2 ); Asynchronous JavaScript
  54. function pw_async_up() { wp_script_add_data( 'picturefill', 'group', 0 ); wp_script_add_data( 'pwcc-scripts',

    'group', 0 ); } add_action( 'wp_enqueue_scripts', 'pw_async_up' , 99 ); Asynchronous JS in the header
  55. function pw_async_up() { wp_script_add_data( 'picturefill', 'group', 0 ); wp_script_add_data( 'pwcc-scripts',

    'group', 0 ); } add_action( 'wp_enqueue_scripts', 'pw_async_up' , 99 ); Asynchronous JS in the header pwcc.cc/wceu/asyncjs
  56. Browsers initiate requests The blocking nature of HTTP 1

  57. Blockers HTML

  58. Blockers HTML CSS

  59. Blockers HTML CSS

  60. Blockers HTML CSS IMG IMG IMG FONTS

  61. Blockers HTML CSS IMG IMG IMG JS FONTS

  62. Blockers HTML CSS IMG IMG IMG JS IFRAME FONTS

  63. Waterfall WebPageTest - webpagetest.org

  64. Waterfall WebPageTest - webpagetest.org

  65. Waterfall HTML CSS IMG IMG IMG JS IFRAME FONTS

  66. Waterfall HTML CSS IMG IMG IMG JS IFRAME FONTS

  67. HTTP/2 An aside

  68. Everything you know about performance is now wrong and former

    best practices are now an anti-pattern and considered harmful.
  69. These titles are considered harmful

  70. Sites using HTTP/2 w3techs.com, March 2016

  71. caniuse.com/http2, March 2016

  72. caniuse.com/http2, March 2016

  73. Critical Path CSS

  74. w3.org/TR/preload/

  75. HTTP/2, without critical path CSS HTML CSS

  76. HTTP/2, without critical path CSS HTML CSS

  77. HTTP/1, with critical path CSS HTML CSS

  78. <html> <head> <style>html{font-family:sans-serif;-ms-text-size-adjust: 100%;-webkit-text-size-adjust:100%}body{margin:0}article, aside,details,figcaption,figure,footer,header,hgroup,main, nav,section,summary{display:block}audio,canvas,progress, video{display:inline-block;vertical-align:baseline} audio:not([controls]){display:none;height:0}[hidden], template{display:none}a{background:transparent}a:active, a:hover{outline:0}abbr[title]{border-bottom:1px

    dotted} b,strong{font-weight:bold}dfn{font-style:italic}h1{font-
  79. HTTP/1, with critical path CSS HTML CSS

  80. HTTP/1, without critical path CSS HTML CSS

  81. HTTP/1, without critical path CSS HTML CSS

  82. CSS, the WordPress way wp_enqueue_style( 'pwcc-style', // handle get_stylesheet_uri(), //

    source array(), // no dependancies '20160624-26', // version 'all' // media );
  83. Preloading CSS

  84. Preloading CSS

  85. Preloading CSS Link: </style.css>; rel=preload; as=style; nopush

  86. Preloading CSS Link: </style.css>; rel=preload; as=style; nopush

  87. Preloading CSS pwcc_preload_style( 'pwcc-style' ); // push pwcc_preload_style( 'pwcc-style', false

    ); // no push
  88. Server push pwcc_preload_style( 'pwcc-style' );

  89. Server push if ( is_cached( 'pwcc-style' ) ) { pwcc_preload_style(

    'pwcc-style' ); } else /* file not cached */ { pwcc_preload_style( 'pwcc-style', false ); }
  90. $version = '20160624-26'; setcookie( 'pwcc-style', $version, 0, '/' ); Server

    push
  91. is_cached() function is_cached( $handle, $version ) { if ( $version

    === $_COOKIE[ $handle ] ) { return true; } else { return false; } }
  92. <html> <head> <style>html{font-family:sans-serif;-ms-text-size-adjust: 100%;-webkit-text-size-adjust:100%}body{margin:0}article, aside,details,figcaption,figure,footer,header,hgroup,main, nav,section,summary{display:block}audio,canvas,progress, video{display:inline-block;vertical-align:baseline} audio:not([controls]){display:none;height:0}[hidden], template{display:none}a{background:transparent}a:active, a:hover{outline:0}abbr[title]{border-bottom:1px

    dotted} b,strong{font-weight:bold}dfn{font-style:italic}h1{font-
  93. None
  94. pwcc.cc/go/loadcss

  95. Register loadCSS wp_register_script( 'pwcc-load-css', // handle '/loadcss.js', // file array(),

    // dependencies "1.2.0", // version true // load in footer );
  96. <style type='text/css'>/* Critical CSS */</style> <link rel='preload' href='/style.css' as='style' onload='this.rel="stylesheet"'>

    <noscript> <link rel='stylesheet' href='/style.css' /> </noscript> HTML: uncached HTTP/1
  97. if ( ! is_cached( 'pwcc-style' ) && ! is_http2() )

    { print_style_inline( 'pwcc-style' ); wp_enqueue_script( 'pwcc-load-css' ); } Inline CSS
  98. if ( ! is_cached( 'pwcc-style' ) && ! is_http2() )

    { print_style_inline( 'pwcc-style' ); wp_enqueue_script( 'pwcc-load-css' ); } Inline CSS pwcc.cc/wceu/rapidcss
  99. <html> <head> <style>html{font-family:sans-serif;-ms-text-size-adjust: 100%;-webkit-text-size-adjust:100%}body{margin:0}article, aside,details,figcaption,figure,footer,header,hgroup,main, nav,section,summary{display:block}audio,canvas,progress, video{display:inline-block;vertical-align:baseline} audio:not([controls]){display:none;height:0}[hidden], template{display:none}a{background:transparent}a:active, a:hover{outline:0}abbr[title]{border-bottom:1px

    dotted} b,strong{font-weight:bold}dfn{font-style:italic}h1{font-
  100. <link rel="stylesheet" href="/style.css" /> Cached Stylesheet

  101. <link rel='shortcut icon' href='/favicon.ico'> <link rel='apple-touch-icon' sizes='57x57' href='/….png'> <link rel='apple-touch-icon'

    sizes='114x114' href='/….png'> <link rel='apple-touch-icon' sizes='72x72' href='/….png'> <link rel='apple-touch-icon' sizes='144x144' href='/….png'> <link rel='apple-touch-icon' sizes='60x60' href='/….png'> <link rel='apple-touch-icon' sizes='120x120' href='/….png'> <link rel='apple-touch-icon' sizes='76x76' href='/….png'> <link rel='apple-touch-icon' sizes='152x152' href='/….png'> <link rel='icon' type='image/png' href='/….png'> <link rel='icon' type='image/png' href='/….png' sizes='160x160'> <link rel='icon' type='image/png' href='/….png' sizes='96x96'> <link rel='icon' type='image/png' href='/….png' sizes='16x16'> <link rel='icon' type='image/png' href='/….png' sizes='32x32'> <meta name='msapplication-TileColor' content='#006ef6'> <meta name='msapplication-TileImage' content='/….png'> <meta name='msapplication-config' content='/browserconfig.xml'>
  102. Everything you know about performance is now wrong and former

    best practices are now an anti-pattern and considered harmful.
  103. Everything you know about performance is now twice as complicated.

  104. Thank you Peter Wilson • peterwilson.cc • @pwcc