Slide 1

Slide 1 text

Speed at Scale WebPerf Tips & Tricks From The Trenches 2019 Google I/O Katie Hempenius @katiehempenius Addy Osmani @addyosmani

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

addEventListener('')

Slide 4

Slide 4 text

Interactivity impacts rage clicks Based on Akamai’s 2018 research into UX & Metrics that matter

Slide 5

Slide 5 text

Page Weight Percentiles

Slide 6

Slide 6 text

Sending too much to the browser

Slide 7

Slide 7 text

Proprietary + Confidential Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem Delightful user experiences can be found everywhere

Slide 8

Slide 8 text

Performance Budgets

Slide 9

Slide 9 text

Cleaning up your site 6 months in

Slide 10

Slide 10 text

40% of brands regress on web performance after 6 months. Internal Google study into Web Performance investments by large brands.

Slide 11

Slide 11 text

Performance budgets set standards for the performance of your site.

Slide 12

Slide 12 text

Time < 2 second TTI KB KB Resources < 150KB JS Lighthouse 90+ Perf Score

Slide 13

Slide 13 text

Catch issues before they ship “Checking the size of our builds ensures that we don’t miss potential performance issues. For example, this has caught dependencies being added unnecessarily. Since the PR was blocked, we were able to pinpoint the issue and fix it before it impacted our build." “By setting a budget for tracking, and reporting build size deltas, we've prevented changes that would have increased metrics like TTI, TTFMC and Time to First Tweet by over 100%.” Paul Armstrong, Twitter Jeff McRiffey, Walmart eCommerce

Slide 14

Slide 14 text

Job checks and logs the size of all builds. PRs fail if size increases by > 1% (main bundles only) Issues are escalated to a performance engineer. > node bundle-check.js +4.4% - discoveryJS +0.0% - discoveryCSS +0.0% - coreJS -0.0% - checkoutJS +0.0% - checkoutCSS

Slide 15

Slide 15 text

Build tracker comments on PRs with a detailed breakdown of changes. Build tracker logs the size of all production builds. Engineers use this info when reviewing PRs.

Slide 16

Slide 16 text

Performance budget tooling for Lighthouse bit.ly/lightwallet-docs LightWallet

Slide 17

Slide 17 text

1. Add a budget.json file 2. Run Lighthouse 5.0+ from the CLI $ lighthouse https://example.com --budgetPath ./budget.json LightWallet bit.ly/lightwallet-docs

Slide 18

Slide 18 text

LightWallet bit.ly/lightwallet-docs

Slide 19

Slide 19 text

[{ "resourceSizes": [ { "resourceType": "image", "budget": 250 }, { "resourceType": "script", "budget": 125 }, { "resourceType": "font", "budget": 30 }, { "resourceType": "document", "budget": 25 }, { "resourceType": "stylesheet", "budget": 5 }, { "resourceType": "third-party", "budget": 400 } ] }]; budget.json Budget types: ● Resource Sizes ● Resource Counts

Slide 20

Slide 20 text

750KB 3.5 MB JavaScript Other Time to Interactive of 3.9 million mobile sites Median: 8.9 seconds Data source: HTTP Archive

Slide 21

Slide 21 text

f(JS KB, Non-JS KB ) →TTI bit.ly/perf-budget-calculator Performance Budget Calculator

Slide 22

Slide 22 text

4.1s Range: 3.2-5.1s 5.1s Range: 4.1-6.4s 6s Range: 4.8-7.5s 100 KB JS 200 KB JS 300 KB JS 300 KB other 300 KB other 300 KB other bit.ly/perf-budget-calculator

Slide 23

Slide 23 text

Image CDN Lazy-loading Responsive Images

Slide 24

Slide 24 text

Lazy Loading

Slide 25

Slide 25 text

Am I a joke to you? Data Plan 5MB Images a page ~4.7MB images at P90 from HTTP Archive

Slide 26

Slide 26 text

Lazy-load offscreen images Eager Loading Load images right away Lazy Loading Load (offscreen) images on-demand 2MB 1MB Potential Savings 3MB (P90) and 416KB (Median)

Slide 27

Slide 27 text

Solid Color 1KB 13KB Progressive image loading LQIP (Low-quality placeholder) Lazy-loading images with JS Common

Slide 28

Slide 28 text

Optimizing Chrome.com Faster page load times (mobile) 20% Faster page load times (desktop - Windows) 26% chrome.com Credits: Vitaly Keyzla (Dev Lead, Infra) Wei-Hsin Chen (Senior Eng/Lead) Luis Villalba (Senior Eng/Lead) Felipe Angel (Eng) Cristian Perez (QA) Katia Pena (QA Lead) Luis Jimenez (Director QA) Neil Shankar (UI Designer) Melissa Castano (Senior UI Designer) Esteban Lobo Guerrero (UI/UX Designer) McKenzy Germain (Web Product Manager) Kevin Furuichi (Android/Chrome Program Manager) Adam Dunlavey (Senior Web Analyst)

Slide 29

Slide 29 text

Lazy-Load Offscreen Images Fewer Image Bytes Loaded Upfront 46% Chrome.com lazy-loads offscreen images. They use an SVG placeholder with image dimensions to avoid reflow. Their custom JS lazy-loader leverages Intersection Observer.

Slide 30

Slide 30 text

Lazy-load offscreen images Defer render until decode Before After Initial state Final state Or download if img.decode() unsupported

Slide 31

Slide 31 text

View Preview Experience

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

Page load from server Page load after auto-loading all rows

Slide 34

Slide 34 text

Optimized CPU load, memory & network traffic Images 4.4MB Images 1.2MB Full Page Load Initial Page State ...leading to faster start times for video previews. DOM Nodes 11,744 Memory 45MB DOM Nodes 650 Memory 8MB bit.ly/netflix-previews

Slide 35

Slide 35 text

46% Image Byte Savings After switching to image lazy-loading 72% 94% 76% 90% 78%

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

Introducing native image lazy-loading! Eager Loading Lazy Loading 2MB 1MB chrome://flags/#enable-lazy-image-loading

Slide 38

Slide 38 text

Introducing native iframe lazy-loading! Eager Loading Lazy Loading 3MB iframe 0MB iframe chrome://flags/#enable-lazy-frame-loading

Slide 39

Slide 39 text

bit.ly/native-lazyload

Slide 40

Slide 40 text

.. .. .. if ('loading' in HTMLImageElement.prototype) { const images = document.querySelectorAll("img.lazyload"); images.forEach(img => { img.src = img.dataset.src; }); } else { // Dynamically load the lazysizes library let script = document.createElement("script"); script.src = "/lazysizes.min.js"; document.body.appendChild(script); } Cross-browser Image lazy-loading Feature Detection JS library fallback

Slide 41

Slide 41 text

Responsive Images

Slide 42

Slide 42 text

101 KB 299 KB vs. Images for desktop & tablet can be ~2-4x larger than the mobile version.

Slide 43

Slide 43 text

By width By density

Slide 44

Slide 44 text

Pixel density ● Limits image pixel density to <= 2x ● Exception: full-screen images where users can pinch zoom. 33% decrease in image size 1x 2x 3x Result: No distinguishable difference to the human eye. 4x

Slide 45

Slide 45 text

Images CDNs

Slide 46

Slide 46 text

Successful image Optimizations

Slide 47

Slide 47 text

Image CDN images fancy

Slide 48

Slide 48 text

Popular Image CDNs Akamai Image Manager | Cloudinary | Imgix | Thumbor (self-hosted) ...cat.jpg?q=50&w=300&h=200 Set quality level to 50 Resize to 300x200

Slide 49

Slide 49 text

Image CDNs "We realized that maintaining an inhouse image optimization solution would be enough work for a dedicated team. By using an Image CDN, our engineers can focus on our core business while our users benefit from fast, good-looking images across all devices & networks." Tobias Baldauf, Trivago

Slide 50

Slide 50 text

Image CDNs ● Auto quality ● Auto cropping ● WebP ● Color channel tuning Decrease in image size (KB) 80%

Slide 51

Slide 51 text

40% 50% 40-60% 71% 80% Image Byte Savings After switching to an image CDN

Slide 52

Slide 52 text

Code-Splitting Defer Third-Party Embeds Expensive Libraries JavaScript

Slide 53

Slide 53 text

Defer Third-Party JavaScript & Embeds

Slide 54

Slide 54 text

57% Patrick Hulce, thirdpartyweb.today. Data from across top 4M sites. 57% JavaScript execution time on the web is third-party code

Slide 55

Slide 55 text

How’s your JavaScript diet going? Me: @StumberVideos

Slide 56

Slide 56 text

Gareth Clubb Everyone wants ‘that tag’ on a page that will make the organisation money. It’s very important to get the right individuals in a room to educate, challenge and work together. Create a Performance Culture

Slide 57

Slide 57 text

Third-party JS 2s 5s bit.ly/telegraph-3p Defer <script defer> bit.ly/telegraph-3p “Our biggest improvement was deferring all JS, including our own” “...this didn’t skew analytics or advertising. Lighthouse Perf +47” Other optimizations 1MB reduction 1st & 3p JS 4s faster “first ad” loading 6s faster Time-to-Interactive

Slide 58

Slide 58 text

When load times decreased 71%, bounce rates decreased 31% Faster Page Load Times 78% Decrease in Bounce Rates 31% Mobile CVR Increase 11% tui.se

Slide 59

Slide 59 text

Before After Defer Google Tag Manager Custom Third-Party Replace A/B Testing Library 50% Reduction domComplete 100KB JS shaved from homepage

Slide 60

Slide 60 text

Loading third-party embeds eagerly has a cost Chrome.com’s Time to Interactive was 13.6s

Slide 61

Slide 61 text

Lazy-load Third-Party Embeds Lighthouse Performance Score (27 to 96) +69 chrome.com Reduction in Time to Interactive (13.6s to 3.1s) 10s Smaller JavaScript Payload 511KB Before After Eagerly load YouTube embeds on page load. Lazy-load YouTube embeds on user interaction.

Slide 62

Slide 62 text

Remove expensive libraries

Slide 63

Slide 63 text

Remove expensive libraries There are other options too: ● Deprecate ● Replace ● Defer ● Update moment.js Bootstrap jQuery

Slide 64

Slide 64 text

lodash → lodash-es momentjs → date-fns fetch → fetch-unfetch async → async-es babel-preset-es2015 →babel-preset-env Replace expensive libraries The one function you care about Importing entire module

Slide 65

Slide 65 text

Defer dependencies ● Tokopedia serves a “lite” version of their app to new users. ● Lite version uses Svelte; service workers precache their React app in the background. React Version Svelte Version vs 320 KB 37 KB JavaScript required to render above-the-fold content

Slide 66

Slide 66 text

lit-html, Preact, & Svelte

Slide 67

Slide 67 text

Update dependencies Improvement in load time 100ms Uplift in revenue per session 0.7% ● Zalando noticed that an older React version was impacting load times. ● Updated from React 15.6.1 to 16.2.0.

Slide 68

Slide 68 text

Code-splitting & Component Loading Loading Render quickly Load minimal useful code Set user expectations Final state

Slide 69

Slide 69 text

Download JS Execution Critical for slow networks Critical for devices with slow CPUs

Slide 70

Slide 70 text

“If JavaScript doesn’t bring users joy, thank it and throw it away” Marie Kondo* * Probably

Slide 71

Slide 71 text

shopping.google.com Above-the-fold-rendering Interactivity for initial view Additional Search features Optimize UI Interactivity JS JS JS Tested on a Moto G4 over 3G Time to Interactive 4.5s Lighthouse Performance 90

Slide 72

Slide 72 text

JavaScript Code-splitting Smaller JavaScript bundle 69% Faster Time-to-Interactive 28% Reduction First-Input-Delay 30% Walmart Grocery split up their JS bundles using granular code-splitting. They removed old / duplicate dependencies and cleaned up A/B test configs. Core bundles are cached with SWs for bytecode caching. grocery.walmart.com

Slide 73

Slide 73 text

Twitter

Slide 74

Slide 74 text

Route-based code-splitting 50% 36% 18% *improvements from Twitter Lite traces, 2017. **This and other optimizations for Twitter Lite’s launch led to a 75% increase in tweets sent. Time to Interactive improvements

Slide 75

Slide 75 text

Review what your tools output! Efficiently bundling i18n for 34 languages Each build included i18n strings invalidating file hashes across the app. Each deploy invalidated your cache. Service Worker had to redownload everything. Issue caused by the tools. Generated files of same size, but different hashes.

Slide 76

Slide 76 text

Lazy-load Translation strings Reduction in overall bundle size 30KB Saved loading Emoji picker on-demand 50KB mobile.twitter.com Internationalization tooling improvements Faster JS exec from new i18n pipeline 80%

Slide 77

Slide 77 text

JavaScript For first-time users Increase in day one plays 54% mWeb users converted to native app installs 30% This and other investments in the mobile web player led to... First time users trying to play a song get a fast sign-up 55KB 300KB Once signed up, the mobile web player is lazy-loaded ~5s Time to Interactive on a Moto G4 over 4G

Slide 78

Slide 78 text

Spotify improved perceived performance Reusing data from one page to hydrate next, reduced API calls & kept blank pages minimum Enables quick navigations between pages, even on slow connections.

Slide 79

Slide 79 text

PRPL Pattern Interactive in 18KB JS Faster Time to Interactive 82% This + other work Improvement in conversions 25% Speed jabong.com Push minimal code to get interactive Render fast Precache other routes (SW) Lazy-load JS On demand HTML CSS JS JS JS JS

Slide 80

Slide 80 text

Fonts

Slide 81

Slide 81 text

Invisible Text By default, if a font is not loaded, the browser will hide text for up to: 3 sec 3 sec 3 sec ∞ Flash of Display font immediately

Slide 82

Slide 82 text

Flash of invisible text Flash of unstyled text

Slide 83

Slide 83 text

@font-face { font-family: 'Google Sans'; src: url(...GoogleSans.woff2) format('woff2'); font-display: swap; } Fonts chrome.com This & other techniques: Improvement in mobile page load times 20% Improvement in “Visually Complete” on 3G .5s

Slide 84

Slide 84 text

fonts.googleapis.com/css?family=Lobster &font-display=swap fonts.googleapis.com/css?family=Lobster &font-display=swap

Slide 85

Slide 85 text

Get important vs meh resources first Why not both? Browser

Slide 86

Slide 86 text

Decrease in Latency 0.7s Preconnect Critical Origins .com Resource Hints Faster Time to Interactive 1.5s Preload Critical Scripts Faster Time to Interactive For future pages 2.7s Prefetch Visible Links bit.ly/quicklinkjs

Slide 87

Slide 87 text

Prefetch Top Search Results Faster Median Above Fold Time (similar to FMP): 1.1s -> 0.39s 759ms eBay prefetch the top 5 items in search results pages for fast subsequent loads. This happens during idle time with requestIdleCallback(). “eBay saw a positive impact on conversions from prefetching”

Slide 88

Slide 88 text

Predictive Asset Prefetching Home Search Item eBay are doing predictive prefetching of static assets. Home prefetches assets for Search. Search prefetches for Item page (and so on). Machine Learning & Analytics based prefetching us under consideration.

Slide 89

Slide 89 text

Prefetch Popular Articles Faster article fetch time 78% Article impressions +13% (after 1 week) +26% (after 2 weeks) Virgilio Sport prefetch articles based on analytics data. Service Workers and prefetch the most clicked posts for users not on 2G. SW updates the top articles every 7m. After 3 weeks 45% Speed Prefetched

Slide 90

Slide 90 text

Critical CSS

Slide 91

Slide 91 text

Fold Inline critical CSS; deliver document in <= 14KB. Load CSS asynchronously. ● filamentgroup/loadcss ● addyosmani/critical ● filamentgroup/criticalcss ● pocketjoso/penthouse Critical CSS Other CSS

Slide 92

Slide 92 text

0s 1s 1.2s 2.4s Improvement in FCP 1.4s Critical CSS

Slide 93

Slide 93 text

Determining Critical CSS Common factors: ● URL ● Device viewport Nikkei also dealt with these factors: ● Login state (logged in/out) ● Subscription (paying/free) ● Paywall (on/off) ● 300KB of “critical” CSS Challenge:

Slide 94

Slide 94 text

Application Server Critical CSS Server User CSS Document with inlined CSS CDN Dynamic Critical CSS API returns critical CSS based on parameters like user state and page. ...?service=article

Slide 95

Slide 95 text

User CSS Document with inlined CSS CDN Application Server Critical CSS Server Edge Side Inclusion (ESI) Caching Inlining ESI params Markup language for assembling documents; CDN feature. Example: <esi:include src="/critical.css?service=article">

Slide 96

Slide 96 text

● +58% conversions (subscriptions) ● +49% daily active users Dynamic Critical CSS Improvement in FCP 1s Reduction in inlined CSS 80% This & other techniques: (without ESI) ● 2x page views per session ● 2.3x organic traffic

Slide 97

Slide 97 text

Brotli

Slide 98

Slide 98 text

Brotli: Reduce bytes over the wire Compress JS & CSS JavaScript reduction 15% Latency Improvement (P50) 37% Decrease in payload size for P75 sized payloads 90% Reduction globally for P95 load latencies. ~15-20% in Emerging Markets 5% Compress API Responses

Slide 99

Slide 99 text

Adaptive serving

Slide 100

Slide 100 text

Before Adaptive Serving Adapt based on network quality & data signals After Reading news navigator.connection.effectiveType // 3g navigator.connection.saveData // true

Slide 101

Slide 101 text

mBasic Site for low-end mTouch mBasic Time To Interactive 1.6s mbasic.facebook.com m.facebook.com Facebook offer a basic version of their site for low-end devices. It has no JavaScript, very limited images and uses minimal CSS with tables mostly for layout.

Slide 102

Slide 102 text

Data Saver Mode For Images Reduction for data-usage from images on web. 96% incl disabled video autoplay 80% Twitter’s Data Saver mode presents images as a preview. The web renders a 64x64 blurred image (LQIP style). Users can tap to load large images. Previews load quick on 2G & 3G. Reduction for data-usage from images on iOS + Android 50%

Slide 103

Slide 103 text

Client-side compression of photo uploads Reduction in cancelled photo uploads ~9.5% On the server, compresses images to JPEG quality 85% & max dimensions of 4096x4096px. On the client, check if images appear above max dimensions or an MB limit. If so, draw to & output quality=85%.

Slide 104

Slide 104 text

Adaptive Serving (Experiment) Before After eBay are experimenting with adaptive serving using effectiveType. On a fast connection, features like product zooming will load on demand. On slow connections, they won’t.

Slide 105

Slide 105 text

No content

Slide 106

Slide 106 text

1. Lazy-loading 2. Responsive Images 3. Image CDNs 4. Defer Third-party JS 5. Remove costly libraries 6. Code-Splitting 7. Avoid FOIT 8. Prefetch 9. Preconnect 10. Preload 11. Critical CSS 12. Brotli 13. Adaptive Serving Get fast web.dev/fast Stay Fast bit.ly/lightwallet-docs Performance Budgets LightWallet

Slide 107

Slide 107 text

Thank you! web.dev/fast bit.ly/lightwallet Helpful resources Katie Hempenius @katiehempenius Addy Osmani @addyosmani