Slide 1

Slide 1 text

Addy Osmani Ewa Gasperowicz Web Performance Made Easy

Slide 2

Slide 2 text

What makes a web page feel heavy? 1.5MB 800KB Images 350KB JavaScript 15s to load & get interactive HTTP Archive

Slide 3

Slide 3 text

Lean and yet full of content

Slide 4

Slide 4 text

Why does performance matter?

Slide 5

Slide 5 text

How important is speed to users? Speed Matters, Vol. 3 24% How attractive the site looks 58% How simple the site is to use 61% How well the site fits my screen 66% How easy it is to find what I’m looking for 75% The speed it takes to load the page UX HIERARCHY

Slide 6

Slide 6 text

“Send less stuff!”

Slide 7

Slide 7 text

Paul Irish in your pocket.

Slide 8

Slide 8 text

New Lighthouse Web Performance Audits bit.ly/lighthouse-perf

Slide 9

Slide 9 text

JavaScript Boot-up Time Preload key requests Avoid multiple, costly round trips to any origin (preconnect) Use a video format for animated content (instead of GIF) Main thread work breakdown Unminified JavaScript & CSS Unused CSS rules All text remains visible during webfont loads Uses efficient cache policy on static assets New Lighthouse Audits New Lighthouse Audits

Slide 10

Slide 10 text

Fixing web performance is as easy as drawing a horse Van Oktorp (insp) 1. Draw 2 circles 2. Draw the legs 3. Draw the face 4. Draw the HAIR 5. Add small details

Slide 11

Slide 11 text

Google Doodles google.com/doodles

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

Let’s start our journey. Doodle: Pony Express

Slide 14

Slide 14 text

Lighthouse. 23 score 15s TTI

Slide 15

Slide 15 text

Unnecessary resources Send less stuff and fewer bytes CHALLENGE vs.

Slide 16

Slide 16 text

Minify and compress JavaScript and CSS const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const webpackConfig = { plugins: [ new UglifyJsPlugin({...}) ] } Before After $ firebase deploy

Slide 17

Slide 17 text

Inefficient cache policies Firebase.json: "source": "**/*.@(jpg|jpeg|gif|png|woff2)", "headers": [{ "key": "Cache-Control", "value": "max-age=31536000" }] Short cache lifetimes can impact repeat visits After

Slide 18

Slide 18 text

Solution ● Minimize code ● Automate minification ○ UglifyJS ○ Cloudflare ○ mod_pagespeed ● Compress (gzip, brotli) ● Cache wherever possible Review the legal playbook to learn how to source imagery, amongst other important legal guidelines: go/iospeakerplaybook. For every image used in the deck, add source details in the “For Legal Review” slide. Remove unnecessary bytes and don’t send things twice

Slide 19

Slide 19 text

JS and CSS Code Unused Scripts with unused code slowing page load CHALLENGE

Slide 20

Slide 20 text

Unused code can surprise us Doodle: Halloween 2016

Slide 21

Slide 21 text

Check Code Coverage 95% unused

Slide 22

Slide 22 text

If we drop MVC adapter our styles drop to 10KB! Vue MDC Adapter We have almost no unused CSS now 194 kB 9.8 kB

Slide 23

Slide 23 text

Sanity check: Perf is up, how about UX? Before After

Slide 24

Slide 24 text

Did we miss anything? One component was using MDC. We can manually copy/paste the lines needed to fix.

Slide 25

Slide 25 text

Solution ● Code Coverage in DevTools ○ Page load ○ Runtime ● Lighthouse Coverage Audit ● Remove unused code to improve page load time ● Test for regressions Review the legal playbook to learn how to source imagery, amongst other important legal guidelines: go/iospeakerplaybook. For every image used in the deck, add source details in the “For Legal Review” slide. Remove unused JavaScript & CSS from the critical path.

Slide 26

Slide 26 text

Bloa CHALLENGE More crap Crap Useful content A “modern” web page d e WebPages t

Slide 27

Slide 27 text

Detect enormous network payloads 3.2MB payload

Slide 28

Slide 28 text

The fastest request is the one not made. Doodle: Pony Express

Slide 29

Slide 29 text

JavaScript Bundle Auditing `unicode` is 1.6MB parsed JS import-cost for Visual Code npm run build --report BundlePhobia Webpack Bundle Analyzer

Slide 30

Slide 30 text

Auditing JavaScript bundles paid off. Before After Bonus: Saved another 320KB discovering an unused dependency! 2.1MB saved 65% smaller

Slide 31

Slide 31 text

Solution ● Make an inventory of all assets ● Measure value & impact of assets ● Audit your assets regularly Review the legal playbook to learn how to source imagery, amongst other important legal guidelines: go/iospeakerplaybook. For every image used in the deck, add source details in the “For Legal Review” slide. Eliminate unnecessary downloads.

Slide 32

Slide 32 text

JavaScript Boot-up Time Is High CHALLENGE Video: Kevin Schaaf

Slide 33

Slide 33 text

Credit: Susie Lu

Slide 34

Slide 34 text

JavaScript Boot-up time is high import DoodleHome from './DoodleHome' import DoodleBrowse from './DoodleBrowse' import DoodleFullscreen from './DoodleFullscreen' import DoodleOffline from './DoodleOffline' Before code-splitting (static import) 1.8s boot-up

Slide 35

Slide 35 text

Use JavaScript Code-splitting Split by route Split by component

Slide 36

Slide 36 text

Code-splitting reduced JavaScript Boot-up Time const DoodleHome = () => import('./DoodleHome') const DoodleBrowse = () => import('./DoodleBrowse') const DoodleFullscreen = () => import('./DoodleFullscreen') const DoodleOffline = () => import('./DoodleOffline') After code-splitting (dynamic import) 0.78s boot-up 56% faster

Slide 37

Slide 37 text

Solution ● Only send code users need. ● Use code-splitting ○ Split routes ○ Split components ○ Split vendor bundles ● Consider tree-shaking ● Serve modern, smaller JS bundles to modern browsers ● Remove unused library code with bit.ly/webpack-libs Review the legal playbook to learn how to source imagery, amongst other important legal guidelines: go/iospeakerplaybook. For every image used in the deck, add source details in the “For Legal Review” slide. Fast JS = fast at Download Parse Compile Execute

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

Unoptimized Images Images that are large, inefficient or unnecessary CHALLENGE

Slide 40

Slide 40 text

Lighthouse Image Audits

Slide 41

Slide 41 text

ImageOptim (Mac) XNConvert (Cross-platform) Build Process Roll your own CDN imagemin libvips Thumbor ImageFlow GUI CDN Cloudinary Imgix Fastly Akamai Image Optimization Tools

Slide 42

Slide 42 text

After Optimize Images Lighthouse is happy too Before Optimize Images Properly size images Serve images in next-gen formats 1.21 mB 100 kB

Slide 43

Slide 43 text

Animated GIFs can be expensive

Slide 44

Slide 44 text

7.3MB 960KB 1.3MB 80%+ savings Replace Animated GIFs with ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4

Slide 45

Slide 45 text

4G+ get 2G-3G get static ~1MB ~30KB Adapt based on user’s effective network connection navigator.connection.effectiveType

Slide 46

Slide 46 text

Doodle Slider Carousels often load unnecessary images

Slide 47

Slide 47 text

LazySizes import lazysizes from 'lazysizes' 1. Include library 2. Use

Slide 48

Slide 48 text

Solution ● Optimize images ● Use responsive Images ○ , ○ Media Queries ○ Client-hints ● Use lighter formats (SVG, video) ● Lazy-load offscreen images Review the legal playbook to learn how to source imagery, amongst other important legal guidelines: go/iospeakerplaybook. For every image used in the deck, add source details in the “For Legal Review” slide. Don’t serve unoptimized or unnecessary images to your users.

Slide 49

Slide 49 text

https://images.guide Image Optimisation Book

Slide 50

Slide 50 text

Resources Discovered & Delivered Late PROBLEM

Slide 51

Slide 51 text

Let the browser know what’s important to fetch. Doodle: Celebrating 50 years of kids coding

Slide 52

Slide 52 text

Mask connection latency with rel=preconnect ▾ Avoid multiple, costly round trips to any origin 300 ms Google Fonts stylesheets + Web Fonts Origin Potential Savings https://fonts.googleapis.com 300 ms https://fonts.gstatic.com 300 ms Avoid multiple, costly round trips to any origin 0.3s faster

Slide 53

Slide 53 text

▾ Preload key requests URL Potential Savings ../Montserrat.woff2 (fonts.gstatic.com) 790 ms ../Teko.woff2 (fonts.gstatic.com) 800 ms Preload key requests 800 ms Web Fonts

Slide 54

Slide 54 text

Web Fonts: with and without 1s saved Diagram is for illustrative purposes only

Slide 55

Slide 55 text

Self-host Web Fonts for maximum control Pros font-display unicode-range Easier subsetting Cons Lose Google Fonts cache-hit rate Lose Google Fonts server optimizations Have to check for updates google-webfonts-helper url('https://fonts.gstatic.com/s/montserrat/v12/JTUSjIg1_i6t8kCHKm 459WRhyyTh89ZNpQ.woff2') format('woff2'); Works around Google Fonts URLs expiring or changing

Slide 56

Slide 56 text

Solution ● Connecting to critical origins? ○ ● Asset for current page? ○ ○ preload-webpack-plugin ● Asset for future navigation? ○ ○ webpack 4.6 (prefetch, preload) Review the legal playbook to learn how to source imagery, amongst other important legal guidelines: go/iospeakerplaybook. For every image used in the deck, add source details in the “For Legal Review” slide. Help browsers deliver critical resources early.

Slide 57

Slide 57 text

/* critical-path styles */ fetch('/api/related.json', { importance: 'low' }); Experimental Feature: Priority Hints github.com/WICG/priority-hints

Slide 58

Slide 58 text

Image Carousel Browser prioritized images Image Carousel Fix using Start images Middle images 2s saved

Slide 59

Slide 59 text

Invisible Text While Web Fonts Load PROBLEM Request page Get HTML Get CSS Get Web Font Blocked text painting Render blocking A

Slide 60

Slide 60 text

Flash of invisible text Fully loaded Web Font Avoid invisible text while Web Fonts are loading

Slide 61

Slide 61 text

font-display @font-face { font-family: 'Montserrat'; font-style: normal; font-display: swap; font-weight: 400; src: local('Montserrat Regular'), local('Montserrat-Regular'), /* Chrome 26+, Opera 23+, Firefox 39+ */ url('montserrat-v12-latin-regular.woff2') format('woff2'), /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ url('montserrat-v12-latin-regular.woff') format('woff'); } font-display: [swap | optional | block | fallback | auto]

Slide 62

Slide 62 text

font-display

Slide 63

Slide 63 text

Solution ● font-display: swap or optional ● ● Web Font subsetting ● Font Loading API ● Use SVGs instead of icon fonts ● For more, see Zach Leatherman’s Web Font recipes at bit.ly/webfont-recipes Review the legal playbook to learn how to source imagery, amongst other important legal guidelines: go/iospeakerplaybook. For every image used in the deck, add source details in the “For Legal Review” slide. Have a Web Font loading strategy.

Slide 64

Slide 64 text

Render-blocking Scripts External stylesheets block first paint of your page PROBLEM

Slide 65

Slide 65 text

Perceived performance could be improved External stylesheets impacted our metrics Reduce render-blocking stylesheets opportunity

Slide 66

Slide 66 text

Critical path optimisation Tools Critical Penthouse loadCSS /* Inlined critical styles */

Slide 67

Slide 67 text

Critical path optimisation Before After 1.2s saved on FMP + TTI

Slide 68

Slide 68 text

Solution ● Inline critical styles in and preload/async load the rest ● Split styles into separate files organized by media query ● Mark non-critical scripts with the defer attribute or lazy-load Review the legal playbook to learn how to source imagery, amongst other important legal guidelines: go/iospeakerplaybook. For every image used in the deck, add source details in the “For Legal Review” slide. Reduce render-blocking scripts and stylesheets.

Slide 69

Slide 69 text

Doodle: Tu Be'av 2017 Video of final loading vs initial speed

Slide 70

Slide 70 text

No content

Slide 71

Slide 71 text

github.com/google/oodle-demo

Slide 72

Slide 72 text

The final score 2.6s TTI

Slide 73

Slide 73 text

Case Study Nikkei

Slide 74

Slide 74 text

Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem +230% Organic traffic +58% Conversion rate +40% Daily active users +28% Page-views r.nikkei.com 14s faster

Slide 75

Slide 75 text

● ● ● ● ● ● ● ● ● ● ● Nikkei - Optimizations 43% smaller JS bundles 75% faster loading w/prefetch 94% cache-hit ratio

Slide 76

Slide 76 text

Nikkei - Critical-path CSS optimizations Before After 1s faster FMP

Slide 77

Slide 77 text

PRPL Pattern

Slide 78

Slide 78 text

Machine Learning + Web Performance One More Thing

Slide 79

Slide 79 text

Data-driven User Experiences https://unsplash.com/photos/mcSDtbWXUZU

Slide 80

Slide 80 text

Predict Page Navigations predictjs.firebaseapp.com

Slide 81

Slide 81 text

Data-driven Loading for Web Sites Prefetch next pages a user is likely to visit as they browse. Analyze User Navigations Page Previous Page Path Page Views Exits Metrics Model Next Page Predictions (Markov Chains, Neural Networks, TensorFlow)

Slide 82

Slide 82 text

Data-driven Bundling for Web Apps Prefetch next JavaScript chunks a user is likely to visit as they browse. Analyze User Navigations Page Previous Page Path Page Views Exits Metrics Model Next Page Predictions (Markov Chains, Neural Networks, TensorFlow) Map “Pages” to JavaScript router Bundle JavaScript routes into chunks

Slide 83

Slide 83 text

alpha github.com/guess-js

Slide 84

Slide 84 text

Guess.js: Predictive Fetching Analyze User Navigations Model Next Page Predictions (Markov Chains) Map “Pages” to JavaScript router Bundle JavaScript routes into chunks GA module Guess Parser Guess Webpack Plugin + Experimental support for predictive prefetching for static sites By Minko Gechev, Addy Osmani, Kyle Mathews & Katie Hempenius github.com/guess-js Prefetch next JavaScript chunks a user is likely to visit as they browse.

Slide 85

Slide 85 text

No content

Slide 86

Slide 86 text

Improving performance is a journey. Lots of small changes can lead to big gains. https://www.istockphoto.com/photo/girl-in-red-dress-with-money-gm476238192-65884907

Slide 87

Slide 87 text

Thank you Addy Osmani Google developers.google.com/web/fundamentals/performance developers.google.com/web/tools/lighthouse Helpful resources Ewa Gasperowicz Google @addyosmani @devnook With special thanks to Ward Peeters, Minko Gechev, Kyle Mathews, Katie Hempenius, Dom Farolino, Yoav Weiss, Susie Lu, Yusuke Utsunomiya, Lighthouse & Google Doodles.

Slide 88

Slide 88 text

We want to hear from you! Provide feedback for this session by signing in on google.com/io/schedule