scott jehl - delivering responsibly - beyond tellerrand düsseldorf 2015

78
DELIVERING RESPONSIBLY SCOTT JEHL

Upload: beyond-tellerrand

Post on 03-Aug-2015

310 views

Category:

Internet


1 download

TRANSCRIPT

DELIVERING

RESPONSIBLY

SCOTT JEHL

Responding

https://www.flickr.com/photos/adactio/6153522068/

Basic Enhanced

Foremost: We Must Deliver.

Speed broadens access.

Performance Priorities

Speed broadens access.

Not just a matter of empathy. Access is our job.

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

Lightening our load

Optimizing everything that you can.

Easy, classic performance optimizations:

Optimize, Minify, Gzip

Don’t just optimize images; Make them responsive!

<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.

Optimizing Assets: A Lesser Concern?

“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/

Prioritizing for progressive rendering

The Critical Path

Heading Heading

<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> ...

Detours on the path to a usable render

HTMLCSS

JS

CSS

JS

Blank page}

Stay on that critical path!

http://webpagetest.org

Sub-1 Second Render: Cram your initial view into the first 14kb of your HTML

“ Identify and “inline” the CSS necessary for

rendering the above-the-fold content

PageSpeed Insights

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

“The fold” varies across devices...

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

Inlining your “critical” code

Load the rest in a non-blocking manner

First the CSS

<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> ...

<link rel=”preload” href=“all.css”>

Fetching the full CSS

<link rel=”preload” href=“all.css” onload=“this.rel=‘stylesheet’”>

Applying the full CSS

Next, inline the critical JavaScript

If you have any...

<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

<script src=”enhancements.js” async defer></script>

Or, async/defer is a good option…

!

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>

Avoiding the FOIT.

http://www.filamentgroup.com/lab/font-events.html

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"; });

Progressive font rendering

Standard

Optimized

Coming soon: CSS-based font-rendering!

@font-face { font-family: foo; ... } body > h1 { font-family: foo; font-rendering: swap 3s; }

Perceived Performance Case Study

3G/Chrome First Usable Render: ~12.5 secs

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)

3G/Chrome First Usable Render: 3.9 secs

Wired.com rendering: before & after

3.9 secs 12.5 secs

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

Looking Ahead

“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

This won’t happen overnight.

Delivering responsibly is our job.

Thanks!@scottjehl, http://filamentgroup.com