A presentation at WordCamp Europe 2016 in in Vienna, Austria by Peter Wilson
Wed 29 Oct 1969 ~ ucla$ ░
Wed 29 Oct 1969 ~ ucla$ ░
Wed 29 Oct 1969 ~ ucla$ l o
░
gin
Wed 29 Oct 1969 ~ ucla$ l o
░ ░
Seven times faster: a study in front-end optimisation Peter Wilson • peterwilson.cc • @pwcc
WordPress is slow
Front-end code is slow
Bytes on the page
Total page size (MB) Nov 2011 - March 2016 0.5 1.0 1.5 2.0 2.5 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
Assets per page Nov 2011 - March 2016 20 40 60 80 100 120 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
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
Load time httparchive.org/trends.php , March 2016
Load time Start render: 4.2 seconds
Load time Visually complete: 12.7 seconds
Load time Document complete: 15.23 sec
Two seconds
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+
The average site kills conversions.
Measure a starting point
WebPageTest - webpagetest.org
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
Timeline view
Comparison timelines Additional blocking request in HTML Header Timed using WebPageTest - pwcc.cc/wceu/blocking 0.5s 1.0s 1.5s 2.0s 0% 0% 0% 100% 0% 86% 100% Blocked Unblocked
53 / 100 Our PageSpeed score is you won’t believe how much it’s costing
What will get my visitors reading quickest? “ ”
Doing it wrong
JavaScript in the footer
All visitors have JavaScript disabled while it downloads. – Every progressive enhancement advocate ever “ ”
wp_enqueue_script(
'pwcc-scripts' , // handle
'/functions.js' , // source
null , // no dependancies
'20160624-26' , // version
true
// load in footer ); JavaScript, the WordPress way
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
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
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
< html
< head
<
script
'jquery.js'
<!--32kB--></ script
<
script
'jquery-migrate.js'
<!--4.4kB--></ script
</ head
< body
<!-- Site content. --> <
script
'/functions.js'
</ script
</ body
jQuery, doing_it_wrong()
< html
< head
<
script
'jquery.js'
<!--32kB--></ script
<
script
'jquery-migrate.js'
<!--4.4kB--></ script
</ head
< body
<!-- Site content. --> <
script
'/functions.js'
</ script
</ body
</ html
jQuery, doing_it_wrong()
The WordPress way blocks rendering Daniel Zedda (CC) - flic.kr/p/a6wwAh
function
pwcc_jquery_to_footer () {
if ( is_admin() )
return ;
w p _ s c r i p t _ a d d _ d a t a (
'jquery' , 'group' , 1 ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery-core' , 'group' , 1 ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery-migrate' , 'group' , 1 ); } add_action( 'wp' , 'pwcc_jquery_to_footer' ); jQuery, doing_it_wrong()
function
pwcc_jquery_to_footer () {
if ( is_admin() )
return ;
w p _ s c r i p t _ a d d _ d a t a (
'jquery' , 'group' , 1 ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery-core' , 'group' , 1 ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery-migrate' , 'group' , 1 ); } add_action( 'wp' , 'pwcc_jquery_to_footer' ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery' , 'group' , 1 ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery-core' , 'group' , 1 ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery-migrate' , 'group' , 1 ); jQuery, doing_it_wrong()
function
pwcc_jquery_to_footer () {
if ( is_admin() )
return ;
w p _ s c r i p t _ a d d _ d a t a (
'jquery' , 'group' , 1 ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery-core' , 'group' , 1 ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery-migrate' , 'group' , 1 ); } add_action( 'wp' , 'pwcc_jquery_to_footer' ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery' , 'group' , 1 ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery-core' , 'group' , 1 ); w p _ s c r i p t _ a d d _ d a t a ( 'jquery-migrate' , 'group' , 1 ); jQuery, doing_it_wrong()
< html
< head
<
script
'jquery.js'
<!--32kB--></ script
<
script
'jquery-migrate.js'
<!--4.4kB--></ script
</ head
< body
<!-- Site content. --> <
script
'/functions.js'
</ script
</ body
jQuery, the WordPress way
< html
< head
<!-- HTML Header. --></
head
< body
<!-- Site content. --> <
script
'jquery.js'
<!--32kB--></ script
<
script
'jquery-migrate.js'
<!--4.4kB--></ script
<
script
'/functions.js'
</ script
</ body
</ html
jQuery, doing_it_wrong()
< html
< head
<!-- HTML Header. --></
head
< body
<!-- Site content. --> <
script
'jquery.js'
<!--32kB--></ script
<
script
'jquery-migrate.js'
<!--4.4kB--></ script
<
script
'/functions.js'
</ script
</ body
</ html
jQuery, doing_it_wrong() pwcc.cc/wceu/jqueryfooter
A s y n c h r o n o u s J a v a S c r i p t
Asynchronous JavaScript < script
'text/javascript'
'/path/file.js'
async
</ script
Asynchronous JavaScript < script
'text/javascript'
'/path/file.js'
async
</ script
async
function
pwcc_async_js ( $tag, $handle ) {
switch ( $handle ) {
case
'pwcc-scripts' :
$tag
=
str_replace ( '></script' , ' async></script' , $tag );
}
return $tag; }
Asynchronous JavaScript
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
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
function
pwcc_async_js ( $tag, $handle ) {
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
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
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
Browsers initiate requests The blocking nature of HTTP 1
Blockers HTML
Blockers HTML CSS
Blockers HTML CSS
Blockers HTML CSS IMG IMG IMG FONTS
Blockers HTML CSS IMG IMG IMG JS FONTS
Blockers HTML CSS IMG IMG IMG JS IFRAME FONTS
Waterfall WebPageTest - webpagetest.org
WebPageTest - webpagetest.org
Waterfall
Waterfall HTML CSS IMG IMG IMG JS IFRAME FONTS
Waterfall HTML CSS IMG IMG IMG JS IFRAME FONTS
HTTP/2 An aside
Everything you know about performance is now wrong and former best practices are now an anti-pattern and considered harmful.
These titles are considered harmful
Sites using HTTP/2 w3techs.com , March 2016
caniuse.com/http2 , March 2016
caniuse.com/http2 , March 2016
Critical Path CSS
w3.org/TR/preload/
HTTP/2, without critical path CSS HTML CSS
HTTP/1, with critical path CSS HTML CSS
< 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 : 1 px
dotted } b , strong { font-weight : bold } dfn { font-style : italic } h1 { font- size : 2 em ; margin : 0.67 em
0 } mark { background : #ff0 ; color : #000 }
HTTP/1, with critical path CSS HTML CSS
HTTP/1, without critical path CSS HTML CSS
CSS, the WordPress way wp_enqueue_style(
'pwcc-style' , // handle
get_stylesheet_uri(),
// source
array (), // no dependancies
'20160624-26' , // version
'all'
// media
);
Preloading CSS
Preloading CSS
Preloading CSS Link: </style.css>; rel=preload; as=style ; nopush
Preloading CSS Link: </style.css>; rel=preload; as=style ; nopush
Preloading CSS pwcc_preload_style ( 'pwcc-style' ); // push pwcc_preload_style ( 'pwcc-style', false ); // no push
Server push pwcc_preload_style ( 'pwcc-style' );
Server push if ( is_cached( 'pwcc-style' ) ) { pwcc_preload_style( 'pwcc-style' ); } else
/* file not cached */ {
pwcc_preload_style(
'pwcc-style' , false ); }
'20160624-26' ; setcookie ( 'pwcc-style' , $version, 0 , '/' ); Server push
is_cached() function
is_cached ( $handle, $version ) {
$_COOKIE[ $handle ] ) {
return
true ;
}
else {
return
false ;
}
}
< 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 : 1 px
dotted } b , strong { font-weight : bold } dfn { font-style : italic } h1 { font- size : 2 em ; margin : 0.67 em
0 } mark { background : #ff0 ; color : #000 }
pwcc.cc/wceu/loadcss
Register loadCSS wp_register_script(
'pwcc-load-css' , // handle
'/loadcss.js' , // file
array (), // dependencies
"1.2.0" , // version
true
// load in footer
);
< style
'text/css'
/* Critical CSS */ </ style
< link
'preload'
'/style.css'
'style'
'this.rel="stylesheet"'
< noscript
<
link
'stylesheet'
'/style.css' />
</ noscript
HTML: uncached HTTP/1
if ( ! is_cached( 'pwcc-style' ) &&
! is_http2() ) { print_style_inline( 'pwcc-style' ); wp_enqueue_script( 'pwcc-load-css' ); } Inline CSS
if ( ! is_cached( 'pwcc-style' ) &&
! is_http2() ) { print_style_inline( 'pwcc-style' ); wp_enqueue_script( 'pwcc-load-css' ); } Inline CSS pwcc.cc/wceu/rapidcss
< 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 : 1 px
dotted } b , strong { font-weight : bold } dfn { font-style : italic } h1 { font- size : 2 em ; margin : 0.67 em
0 } mark { background : #ff0 ; color : #000 }
< link
"stylesheet"
"/style.css" /> Cached Stylesheet
< link
'shortcut icon'
'/favicon.ico'
< link
'apple-touch-icon'
'57x57'
href =' /….png'
< link
'apple-touch-icon'
'114x114'
href =' /….png'
< link
'apple-touch-icon'
'72x72'
href =' /….png'
< link
'apple-touch-icon'
'144x144'
href =' /….png'
< link
'apple-touch-icon'
'60x60'
href =' /….png'
< link
'apple-touch-icon'
'120x120'
href =' /….png'
< link
'apple-touch-icon'
'76x76'
href =' /….png'
< link
'apple-touch-icon'
'152x152'
href =' /….png'
< link
'icon'
'image/png'
href =' /….png'
< link
'icon'
'image/png'
href =' /….png'
'160x160'
< link
'icon'
'image/png'
href =' /….png'
'96x96'
< link
'icon'
'image/png'
href =' /….png'
'16x16'
< link
'icon'
'image/png'
href =' /….png'
'32x32'
< meta
'msapplication-TileColor'
'#006ef6'
< meta
'msapplication-TileImage'
content =' /….png'
< meta
'msapplication-config'
'/browserconfig.xml'
Everything you know about performance is now wrong and former best practices are now an anti-pattern and considered harmful.
Everything you know about performance is now
twice as complicated.
Thank you Peter Wilson • peterwilson.cc • @pwcc
The average web page takes fifteen seconds to load, this can lower the PageSpeed score to the low 30s. Working together web designers and devs can make sites readable in two seconds, working towards a web seven times faster.
Find out how to get a PageSpeed score in the 90s. What are the rules you have to follow, what are those you have to break?
The following resources were mentioned during the presentation or are useful additional information.
Here’s what was said about this presentation on social media.
Page Size increases by @pwcc pic.twitter.com/AR2rDwByZF
— Alex T. (@LX_T) June 24, 2016
Great talk by @pwcc about Performance and how HTTP/2 makes everything even mor ecomplicated. https://t.co/I3cb2NIKrC #WCEU
— Martin Widmann ❤️ (@mwidmann) June 24, 2016
Excelente ponencia sobre optimización por @pwcc. #WCEU pic.twitter.com/SH4E0ZD4E9
— Mauricio Gelves Ⓦ (@maugelves) June 24, 2016
This front end performance talk by @pwcc at #wceu was so so so good.
— Joe McGill (@joemcgill) June 24, 2016
Brilliant talk from @pwcc on frontend optimization in progress right now #wceu pic.twitter.com/xn5lLtEwYu
— Colm Troy (@colmtroy) June 24, 2016
Peter Wilson's talk on optimisation has only been going for five minutes and is easily the best talk I have seen yet at #wceu @pwcc
— Kevin Muldoon (@KevinMuldoon) June 24, 2016
15.23 sec average web page load time. Wow. #wceu @pwcc pic.twitter.com/s384pJDjmN
— Alicia Laing (@creativemode) June 24, 2016
15 seconds of silence while the "average webpage" loads—Peter Wilson @pwcc, @humanmadeltd #WCEU pic.twitter.com/JeZUmTvvcv
— WordCamp Europe (@WCEurope) June 24, 2016
Good technique. @pwcc makes audience wait out the average length of page loading in awkward silence. Makes point well. #wceu
— David Bunce (@davidbunce_web) June 24, 2016
Oh man. @pwcc fills Halle G well above capacity for his performance talk. #WCEU
— Morten Rand-Hendriksen 🇳🇴🇨🇦 (@mor10) June 24, 2016