Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Web Performance Made Easy

Web Performance Made Easy

The web has made great progress in enabling fast experiences, but building a fast site today isn’t trivial. At Google, we analyze a lot of sites and have learned what makes them load quickly and run smoothly. In this talk, learn how to find and fix the most common web performance bottlenecks to improve your UX by using tools like Lighthouse and DevTools, and discover the latest browser APIs to get more control over your loading experience.

Video: https://www.youtube.com/watch?v=Mv-l3-tJgGk

Addy Osmani

May 12, 2018
Tweet

More Decks by Addy Osmani

Other Decks in Technology

Transcript

  1. Addy Osmani Ewa Gasperowicz
    Web Performance
    Made Easy

    View Slide

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

    View Slide

  3. Lean
    and yet
    full of content

    View Slide

  4. Why does
    performance matter?

    View Slide

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

    View Slide

  6. “Send less stuff!”

    View Slide

  7. Paul Irish in your
    pocket.

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  11. Google Doodles
    google.com/doodles

    View Slide

  12. View Slide

  13. Let’s start our journey.
    Doodle: Pony Express

    View Slide

  14. Lighthouse.
    23
    score
    15s
    TTI

    View Slide

  15. Unnecessary resources
    Send less stuff and fewer bytes
    CHALLENGE
    vs.

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  20. Unused code
    can surprise us
    Doodle: Halloween 2016

    View Slide

  21. Check Code Coverage
    95%
    unused

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  27. Detect enormous network payloads
    3.2MB
    payload

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  33. Credit: Susie Lu

    View Slide

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

    View Slide

  35. Use JavaScript Code-splitting
    Split by route
    Split by component

    View Slide

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

    View Slide

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

    View Slide

  38. View Slide

  39. Unoptimized Images
    Images that are large, inefficient or unnecessary
    CHALLENGE

    View Slide

  40. Lighthouse Image Audits

    View Slide

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

    View Slide

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

    View Slide


  43. Animated GIFs can be expensive

    View Slide

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

    View Slide

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

    View Slide

  46. Doodle Slider
    Carousels often load unnecessary images

    View Slide

  47. LazySizes
    import lazysizes from 'lazysizes'


    class="lazyload"/>

    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w"/>
    1. Include library
    2. Use

    View Slide

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

    View Slide

  49. https://images.guide
    Image Optimisation Book

    View Slide

  50. Resources Discovered & Delivered Late
    PROBLEM

    View Slide

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



    View Slide



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

    View Slide

  53. ▾ 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
    type="font/woff2" crossorigin="anonymous">
    Web Fonts

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide



  57. /* critical-path styles */



    <br/>fetch('/api/related.json', { importance: 'low' });<br/>


    Experimental Feature: Priority Hints
    github.com/WICG/priority-hints

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  62. font-display

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  66. Critical path optimisation
    Tools
    Critical
    Penthouse
    loadCSS

    /* Inlined critical styles */
    onload="this.onload=null;this.rel='stylesheet'">






    rel="stylesheet">


    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  70. View Slide

  71. github.com/google/oodle-demo

    View Slide

  72. The final score
    2.6s
    TTI

    View Slide

  73. Case Study
    Nikkei

    View Slide

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

    View Slide












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

    View Slide

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

    View Slide

  77. PRPL Pattern

    View Slide

  78. Machine Learning +
    Web Performance
    One More Thing

    View Slide

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

    View Slide

  80. Predict Page Navigations
    predictjs.firebaseapp.com

    View Slide

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

    View Slide

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

    View Slide

  83. alpha
    github.com/guess-js

    View Slide

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

    View Slide

  85. View Slide

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

    View Slide

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

    View Slide

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

    View Slide