Scott Jehl - Delivering Responsibly - beyond tellerrand Düsseldorf 2015
-
Upload
beyond-tellerrand -
Category
Internet
-
view
310 -
download
1
Transcript of Scott Jehl - Delivering Responsibly - beyond tellerrand Düsseldorf 2015
More people access Facebook over 2G than 4G.
https://twitter.com/BenedictEvans/status/513017790920290304
Benedict Evans
https://www.flickr.com/photos/lacantine/6234723672/
https://fbnewsroomus.files.wordpress.com/2015/02/state-of-connectivity1.pdf
Average webpage: 2 Megabytes!
5%
61kb
152kb
61kb
318kb
1,297kb
IMG JS CSS OTHER HTML FONTS
http://httparchive.org/interesting.php?a=All&l=Apr%2015%202015
<img src="small.jpg" srcset="large.png 2x" alt="…"> !
!
<picture> <source srcset="large.png" media="(min-width: 800px)"> <source srcset="medium.jpg" media="(min-width: 400px)"> <img src="small.jpg" alt="…"> </picture>
Srcset & Picture
http://scottjehl.github.io/picturefill/
Reduce Framework Bloat
Reduce dependencies, make custom library builds, and UnCSS what you can.
“when it comes to your web browsing experience,
it turns out that latency, not bandwidth, is likely the constraining factor today.
Ilya Grigorik
https://www.igvita.com/2012/07/19/latency-the-new-web-performance-bottleneck/
<link rel="stylesheet" href="a.css"> <link rel="stylesheet" href="fonts.css"> <script src="a.js"></script> <script src="b.js"></script>
Detours on the path to a usable render
... </head>
<head> ...
“ Identify and “inline” the CSS necessary for
rendering the above-the-fold content
PageSpeed Insights
https://developers.google.com/speed/pagespeed/insights/
http://paul.kinlan.me/detecting-critical-above-the-fold-css/
Original CSS
h1 { font-size: 1.2em; col… } h2 { margin: 0; } ol { color: red; } li { color: blue; backgrou… } li:hover { color: purple; … } li:first-child { color: gr… } li:last-child { color: pin… } .footer { border-top: 1px … } .copyright { font-size: 1.… }
h1 { font-size: 1.2em; col… } h2 { margin: 0; } ol { color: red; } li { color: blue; backgrou… } li:first-child { color: gr… }
Critical CSS
https://github.com/filamentgroup/grunt-criticalcss
criticalcss: { home: { options: { outputfile : 'css/critical/critical-home.css', filename : 'all.css', url : 'http://fgwebsite.local' } }, services: { options: { outputfile : 'css/critical/critical-services.css', filename : 'all.css', url : 'http://fgwebsite.local/services/' } },
Critical CSS Configuration
<style> body { font-family: sans-serif; } div.foo { … </style>
Inlining critical CSS
... </head>
<head> ...
<style> <% include “path/to/critical/template.css” %> </style>
Inlining critical CSS
... </head>
<head> ...
<style> <% include "critical.css" %> </style> <script> <% include "initial.js" %> </script>
Critical JS, inlined
... </head>
<head> ...
Which JavaScript is “critical?”
• Ideally, none!
• functions for loading additional assets
• Feature tests? Important polyfills?
• Conditional logic for loading files
function loadCSS( href ){ var ss = window.document.createElement( "link" ); var ref = window.document.getElementsByTagName( "script" )[ 0 ]; ss.rel = "stylesheet"; ss.href = href; ss.media = "only x"; ref.parentNode.insertBefore( ss, ref ); setTimeout( function(){ ss.media = "all"; } ); }
loadCSS( “/path/to/all.css” ); !
An async CSS loader for non-critical CSS
function preloadSupport(){ var link = document.createElement('link'); link.rel = 'PRELOAD'; return link.rel == 'preload'; }
Detecting rel=preload support
<link rel=”preload” href=“all.css” id=“allCSS” onload=“this.rel=‘stylesheet’”>
<script> function loadCSS(){ … } function preloadSupport(){ … } if( !preloadSupport() ){ loadCSS( document.getElementById( "allCSS" ).href ); } </script>
<noscript><link href=“all.css” rel=“stylesheet”></noscript>
Polyfilling rel=preload with loadCSS
function loadJS( src ){ var js = document.createElement( "script" ), ref = document.getElementsByTagName( "script" )[ 0 ]; js.src = src; js.async = true; ref.parentNode.insertBefore( js, ref ); } // load a script!
loadJS( “/path/to/enhancements.js” );
A simple async. script file loader
!
if( document.querySelector && document.addEventListener ){ loadJS( "enhancements.js" ); }
…but dynamic loaders let you cut the mustard
... </script> </head>
<head> <script> ...
<style>/* Critical styles go here */ </style>
<link rel=”preload” href=“all.css” as=“stylesheet” id=“allCSS” onload=“this.rel=‘stylesheet’”> <script> /* some functions go here… */ if( !preloadSupport() ){ loadCSS( document.getElementById( "allCSS" ).href ); } if( browserCutsTheMustard ){ loadJS( "enhancements.js" ); } </script> <noscript><link href=“all.css” rel=“stylesheet”></noscript>
Enabling fonts once loaded
h2 { font-family: sans-serif; } .fonts-loaded h2 { font-family: “Source Sans Pro", sans-serif; }
Enabling fonts once loaded
new w.FontFaceObserver( "Source Sans Pro” ) .check() .then( function(){ document.documentElement.className += " fonts-loaded"; });
Coming soon: CSS-based font-rendering!
@font-face { font-family: foo; ... } body > h1 { font-family: foo; font-rendering: swap 3s; }
Optimizations Made:
• Extract and Inline “Critical” CSS
• Load full CSS asynchronously
• Load scripts asynchronously (ads too!)
• Load fonts asynchronously
• Style fallback fonts to match custom font sizes
• Use font loading APIs to swap-in custom fonts once loaded (allow fallback text to show first)
weight does not need to increase wait
How we load stuff matters more than how much stuff we load
http://www.filamentgroup.com/lab/weight-wait.html
“if you have ever inlined a resource (CSS, JS, or an image), you've been
"simulating" server push
Ilya Grigorik
https://www.igvita.com/2013/06/12/innovating-with-http-2.0-server-push/
HTTP/2 means no more:
• Inlining CSS, JS, or images
• Concatenating CSS & JavaScript files
• Domain Sharding
• Image sprites