Slide 1

Slide 1 text

@addyosmani

Slide 2

Slide 2 text

@addyosmani

Slide 3

Slide 3 text

LOAD ONLY WHAT YOU NEED WHEN YOU NEED IT n

Slide 4

Slide 4 text

DON’T BE BIG ✂ Code-split your JavaScript Compress resources ⚡ Minify & optimize *.* Tree-shake modules Respect data plans Don’t over-do Web Fonts ONLY LOAD WHAT YOU NEED Lazy-load non-critical resources Preconnect to important origins Preload critical resources Minimize redirects & round-trips ONLY LOAD WHAT CHANGED Cache resources effectively Be network resilient with Service Workers LOADING BEST PRACTICES

Slide 5

Slide 5 text

User Expectations

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

RESPONSE ANIMATION IDLE LOAD RAIL Evolving

Slide 8

Slide 8 text

First Paint First Meaningful Paint Time To Interactive User happiness metrics First Contentful Paint

Slide 9

Slide 9 text

Time to Interactive <5s on an average mobile device over 3G *2s on repeat-load a:er Service Worker registered goal

Slide 10

Slide 10 text

Latencies are significantly higher than a wired connection

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

Can we data-science the web?

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

THIS CAN’T GO WRONG.

Slide 17

Slide 17 text

NEW GAME OPTIONS A ROAD RASH RIFF

Slide 18

Slide 18 text

PLAYER 1 REMY LEVEL 1 A TOTALLY SAFE ROAD

Slide 19

Slide 19 text

STAGE 1: MEASURE REMY REMY

Slide 20

Slide 20 text

Chrome DevTools Lighthouse WebPageTest TOOLS TO SCIENCE THE WEB Synthetic lab conditions Real-world RUM Synthetic health of the web Puppeteer ~500K sites BETA

Slide 21

Slide 21 text

Queryable RUM for the web?

Slide 22

Slide 22 text

bit.ly/introducing-crux

Slide 23

Slide 23 text

Origin Form Factor Effective Connection Type (e.g 3G, 4G) First Paint First ContentFul Paint domContentLoaded onLoad

Slide 24

Slide 24 text

// Network type that browser uses
 navigator.connection.type > 'wifi' 
 // New: Effective connection type // using rtt and downlink values
 navigator.connection.effectiveType > '2G' I want to adapt serving based on estimated network quality BEFORE AFTER For more on navigator.connection.* See ‘Building a modern media experience’ Chrome 62

Slide 25

Slide 25 text

RUM Chrome UX Report

Slide 26

Slide 26 text

STAGE 2: OPTIMIZE REMY

Slide 27

Slide 27 text

JAVASCRIPT

Slide 28

Slide 28 text

“Networks, CPUs and disks all hate you. On the client, you pay for what you send in ways you can't easily see” - Alex Russell, Chrome

Slide 29

Slide 29 text

http://beta.httparchive.org Using Dev Tools mobile emulation, Moto G4 calibrated CPU, Cable (5/1mbps, 28ms) STATE OF JAVASCRIPT ON MOBILE 1MB 600KB+ 300KB+ 10% sites 25% sites 50% sites

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

JavaScript has a cost. Fast = Fast at Parse Eval Download On mobile devices

Slide 34

Slide 34 text

2017 JavaScript Parse Costs Average Phone ~1MB JavaScript (uncompressed)

Slide 35

Slide 35 text

JavaScript Parse Cost On Mobile - CNN ~9s difference to the A11 With thanks to Pat Meenan

Slide 36

Slide 36 text

PRPL Pattern USED BY SITES LIKE SUPPORTED BY CLIs

Slide 37

Slide 37 text

Where do mobile sites spend their time loading? With thanks to Camillo and Mathias @ V8 Average Housing Forbes Treebo Twitter Trivago Lancome Tech Today OLACabs Wego Konga

Slide 38

Slide 38 text

Removing unused code can reduce network transmission times, CPU-intensive code parsing, and memory overhead

Slide 39

Slide 39 text

CODE COVERAGE

Slide 40

Slide 40 text

40% SITES MAY USE ONLY OF THE JAVASCRIPT THEY LOAD UPFRONT. With thanks to [email protected] JS CODE COVERAGE OF TOP 50 SITES

Slide 41

Slide 41 text

LEARN FROM GAME DEVELOPERS

Slide 42

Slide 42 text

BAKE ONLY WHAT A SECTION REQUIRES INTO BUNDLES THAT CAN BE LOADED AS NEEDED. n

Slide 43

Slide 43 text

Code-splitting // Defines a “split-point” for a separate bundle require.ensure([], () => { const profile = require('./UserProfile', cb); }); import('./UserProfile') .then(loadRoute(cb)) .catch(errorLoading) Webpack 2+ Webpack 1 Also see Splittable, Closure Compiler or Browserify

Slide 44

Slide 44 text

Minify _everything_ Babelified ES5 w/Uglify ES2015+ with babel-minify css-loader + minimize:true Code-splitting Dynamic import() Route-based chunking Tree-shaking Webpack 2+ with Uglify RollUp DCE w/ Closure Compiler Optimize “Vendor” libs NODE_ENV=production CommonsChunk + HashedModuleIdsPlugin() Transpile less code babel-preset-env + modules:false Browserlist useBuiltIns: true Scope Hoisting: Webpack 3 RollUp Strip unused Lodash modules lodash-webpack-plugin babel-plugin-lodash Fewer Moment.js locales ContextReplacementPlugin()

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

Pinterest’s old Mobile Site - 1st load First Paint: 4.2s First Meaningful Paint: 6.2s Time To Interactive: 23s

Slide 47

Slide 47 text

Pinterest’s new Mobile Site - 1st load First Paint: 1.8s First Meaningful Paint: 5.1s Time To Interactive: 5.6s JS Bundles: 620KB ➡ 150KB CSS Bundles: 150KB ➡ 6KB inline P90 for Pin pages: 20s ➡ 6.5s

Slide 48

Slide 48 text

Webpack Bundle Analyzer: Before splitting out common async route code

Slide 49

Slide 49 text

Webpack Bundle Analyzer: After moving out common code from async chunks into entryChunk 60-90% decrease in size of async route chunks (e.g 13.9KB ➡ 1KB) 20% increase in size of entry (59KB ➡ 71KB)

Slide 50

Slide 50 text

INTRODUCE WORKFLOWS THAT FORCE EVERYBODY TO THINK ABOUT LOADING TIMES FROM THE BEGINNING. n

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

Performance Budgets for JS Budgets Tinder tries not to exceed Vendor Async Other 155KB 55KB 35KB CSS 20KB

Slide 53

Slide 53 text

import A from '../A';
 import B from '../B'; 
 const route = [
 {
 route: '/',
 regions: {
 side: A,
 main: B
 }
 }
 ]; JavaScript Route-based code-splitting Before main.js A B

Slide 54

Slide 54 text

import Loadable from ‘react-loadable'; 
 const A = Loadable({
 loader: () => import('../A' /* webpackChunkName: "pc-r-A" */),
 loading: () => null
 }); 
 const B = Loadable({
 loader: () => import('../B' /* webpackChunkName: "pc-r-B" */),
 loading: () => null
 });
 
 const route = [
 {
 route: '/',
 regions: {
 side: A,
 main: B
 },
 preload: [ /* next page chunk to preload*/ ]
 } React Loadable CommonsChunkPlugin After A.js B.js

Slide 55

Slide 55 text

JavaScript Route-based code-splitting + budgets Before Main bundle size: 166kb DOMContentLoad: 5.46s load: 11.91s After Main bundle size: 101kb DOMContentLoad: 4.69s load: 4.69s

Slide 56

Slide 56 text

CACHING

Slide 57

Slide 57 text

* Chrome has 4+ caches. The above reflects the main two - the HTTP and memory caches Chrome’s Cache Hit Rates

Slide 58

Slide 58 text

Cache-Control Policies /page HTML /style.3da37df.css CSS /script.8sd34ff.js JavaScript /photo.jpg Image Cache-Control: max-age=31536000 Cache-Control: no-cache Cache-Control: private, max-age=31536000 Cache-Control: max-age=86400 https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching

Slide 59

Slide 59 text

HTTP Caching Checklist Use consistent URLs and minimize resource churn Provide a validation token (ETag) to avoid transferring unchanged bytes Identify resources that can be cached by intermediaries (like CDNs) Determine the optimal cache lifetime of resources (max-age) Consider a Service Worker for more control over your repeat visit caching 1. 2. 3. 4. 5. bit.ly/caching-checklist

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

Before Service Worker After Service Worker

Slide 62

Slide 62 text

https://jakearchibald.com/2016/caching-best-practices/

Slide 63

Slide 63 text

PRIORITY

Slide 64

Slide 64 text

http://beta.httparchive.org Using Dev Tools mobile emulation, Moto G4 calibrated CPU, Cable (5/1mbps, 28ms) TIME TO INTERACTIVE ON MOBILE 35s 22s 14s 10% sites 25% sites 50% sites

Slide 65

Slide 65 text

No content

Slide 66

Slide 66 text

No content

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

No content

Slide 69

Slide 69 text

No content

Slide 70

Slide 70 text

Chrome 50 Safari 11 Firefox WIP

Slide 71

Slide 71 text


 
 (async () => {
 try {
 const response = await fetch(new Request("movies.json", {credentials: "include"}));
 const data = await response.json();
 console.log(data);
 } catch (exception) {
 console.log("Booo");
 }
 })();
 I have critical resources I want to load earlier than discovery. Chrome 62

Slide 72

Slide 72 text

How are sites are using link rel=preload? BBC News - Stylesheets

Slide 73

Slide 73 text

BBC News - using for their stylesheets

Slide 74

Slide 74 text

36% improvement

Slide 75

Slide 75 text

before after Reduce first paint by 500ms, load time by 1 second

Slide 76

Slide 76 text

~1s saving

Slide 77

Slide 77 text

No content

Slide 78

Slide 78 text

Link element Link header

Slide 79

Slide 79 text

No content

Slide 80

Slide 80 text

No content

Slide 81

Slide 81 text

Express + HTTP/2 Push Headers const express = require('express'), let app = express(); app .use('/js', express.static('js')) .get('/', function (req, res) { res.set('Link', ` ; rel=preload; as='style', ; rel=preload; as='script', ; rel=preload; as='script'`)

Slide 82

Slide 82 text

shop.polymer-project.org

Slide 83

Slide 83 text

HTTP/2 with 3G ~8s

Slide 84

Slide 84 text

<5s

Slide 85

Slide 85 text

HTTP/2 SERVER PUSH, BASICALLY REMY

Slide 86

Slide 86 text

No content

Slide 87

Slide 87 text

No content

Slide 88

Slide 88 text

No content

Slide 89

Slide 89 text

https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/

Slide 90

Slide 90 text

AUTOMATE https://github.com/addyosmani/critical INLINE CRITICAL CSS Critical - extract & inline critical CSS using Chrome Headless /* critical */ /* loadCSS */ inline async

Slide 91

Slide 91 text

Baseline Critical CSS Preload H/2 Push https://speakerdeck.com/patrickhamann/css-and-the-first-meaningful-paint-css-conf-eu-may-2017

Slide 92

Slide 92 text

PAGE WEIGHT

Slide 93

Slide 93 text

http://beta.httparchive.org Using Dev Tools mobile emulation, Moto G4 calibrated CPU, Cable (5/1mbps, 28ms) WEB PAGE WEIGHT ON MOBILE 5.4MB 2.9MB 1.4MB 10% sites 25% sites 50% sites

Slide 94

Slide 94 text

How many sites do not serve content compressed? ~30%

Slide 95

Slide 95 text

GZIP, BROTLI, ZOPFLI Compress!

Slide 96

Slide 96 text

Apache NGINX gzip on; gzip_vary on; gzip_comp_level 6; gzip_http_version 1.1; gzip_proxied any; gzip_min_length 256; gzip_buffers 16 8k; gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript; AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/x-javascript .htaccess nginx.conf

Slide 97

Slide 97 text

No content

Slide 98

Slide 98 text

Brotli Improved load time by 7% in India & 4% U.S bit.ly/linkedin-brotli Decreased the size of static assets by 20% bit.ly/dropbox-brotli 17% improvement for largest JS bundles bit.ly/certsimple-brotli 1.5 petabytes (million gigs) saved a day bit.ly/playstore-brotli

Slide 99

Slide 99 text

Brotli Use: Mostly JavaScript, CSS and HTML From “Tracking the performance of the web with HTTP Archive”

Slide 100

Slide 100 text

Remove unnecessary downloads The fastest and best-optimized resource is a resource not sent. Inventory your own assets and third-party assets on your pages. Measure the perf of each asset: its value and its technical performance. Determine if the resources are providing sufficient value. Lazy-load/defer resources that are non-critical as much as possible. 1. 2. 3. 4. 5.

Slide 101

Slide 101 text

WEB FONTS

Slide 102

Slide 102 text

http://beta.httparchive.org Using Dev Tools mobile emulation, Moto G4 calibrated CPU, Cable (5/1mbps, 28ms) WEB FONT WEIGHT ON MOBILE 200KB 100KB 80KB 10% sites 25% sites 50% sites

Slide 103

Slide 103 text

No content

Slide 104

Slide 104 text

No content

Slide 105

Slide 105 text

https://meowni.ca/font-style-matcher/

Slide 106

Slide 106 text

https://www.zachleat.com/web/comprehensive-webfonts/ “Comprehensive Web Fonts”

Slide 107

Slide 107 text

@font-face {
 font-family: 'Roboto';
 font-display: optional;
 src: url(Roboto.woff) format('woff'),
 url(Roboto.eot) format('eot');
 font-weight: 400;
 font-style: normal;
 } If my Web Fonts can’t load quickly, don’t load them at all. Chrome 60 Safari WIP Firefox WIP

Slide 108

Slide 108 text

No content

Slide 109

Slide 109 text

Slide 110

Slide 110 text

Heaviest use of rel=preload is for Web Fonts HTTPArchive

Slide 111

Slide 111 text

Preloading Web Fonts = 50% (1.2s) improvement in time-to-text-paint

Slide 112

Slide 112 text

Use System Fonts when you can The fastest font is one that doesn’t need to load. Try font-display: optional; If a Web Font can’t load fast, load a fallback instead. If the Web Font is cached, it’ll get used the next time the user loads the page. Try to request Web Fonts with a higher priority If Web Fonts are a critical to your UX, preload them to minimize FOIT. Try subsetting to limit the range of Web Font characters needed Subsetting removes characters & Open-Type features from fonts, reducing file size. Google Fonts, TypeKit & Font Squirrel support it. Be careful with use. Try the CSS Font Loading API if you need more control Track font download progress & apply once fetched, manipulate font faces and override default lazy load behavior. S Have a Web Font Loading Strategy @addyosmani

Slide 113

Slide 113 text

IMAGES

Slide 114

Slide 114 text

http://beta.httparchive.org Using Dev Tools mobile emulation, Moto G4 calibrated CPU, Cable (5/1mbps, 28ms) IMAGE WEIGHT ON MOBILE 3.9MB 1.9MB 0.8MB 10% sites 25% sites 50% sites

Slide 115

Slide 115 text

Image Quality Matters q=80 is a good baseline for web

Slide 116

Slide 116 text

JPEG Encoders

Slide 117

Slide 117 text

https://imageoptim.com www.xnview.com/en/xnconvert/

Slide 118

Slide 118 text

Adapt intelligently H E I G H T Size appropriately WIDTH IMAGE DECODE Compress carefully Take care with tools Prioritize critical images HIGH LOW Lazy-load the rest Choose the right format Image Optimisation

Slide 119

Slide 119 text

No content

Slide 120

Slide 120 text

No content

Slide 121

Slide 121 text

Heavy image decode Lower image decode

Slide 122

Slide 122 text

Data Saver Mode introduced up to 70% savings for Twitter Lite Do this with the browser using the Save-Data client hint

Slide 123

Slide 123 text

ESSENTIAL IMAGE OPTIMIZATION BOOK https://images.guide

Slide 124

Slide 124 text

STAGE 3: MONITOR REMY

Slide 125

Slide 125 text

EVERYONE IS RESPONSIBLE FOR performance.

Slide 126

Slide 126 text

5s

Slide 127

Slide 127 text

No content

Slide 128

Slide 128 text

No content

Slide 129

Slide 129 text

Performance Budget Tools CALIBRE BUNDLESIZE SPEEDCURVE

Slide 130

Slide 130 text

bit.ly/perf-budgets REAL-WORLD WEB PERF BUDGETS

Slide 131

Slide 131 text

PERFORMANCE IS A JOURNEY. LOTS OF SMALL CHANGES CAN LEAD TO BIG GAINS. n

Slide 132

Slide 132 text

KEEP RACING TOWARDS BETTER PERF REMY

Slide 133

Slide 133 text

Thank you