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

Adaptive Loading - Improving the UX for billions on low-end devices

Addy Osmani
November 20, 2019

Adaptive Loading - Improving the UX for billions on low-end devices

Adaptive Loading is a web performance pattern where sites not just respond based on screen size - they adapt based on actual device hardware.

Any user can have a slow experience. In a world with widely varying device capabilities, a "one-size" fits all experience may not always work. Sites that delight users on high-end devices can be unusable on low-end ones, particularly on median mobile and desktop hardware and in emerging markets. What if we could adapt how we deliver pages to better cater for our user's constraints?

https://addyosmani.com/blog/adaptive-loading/
https://web.dev/adaptive-loading-cds-2019/
Video: https://youtu.be/puUPpVrIRkc

Addy Osmani

November 20, 2019
Tweet

More Decks by Addy Osmani

Other Decks in Technology

Transcript

  1. Addy Osmani
    Chrome
    @addyosmani
    Adaptive Loading
    Improving the UX for billions on low-end devices
    Nate Schloss
    Facebook
    @n8schloss

    View full-size slide

  2. Any user can have a slow
    experience.

    View full-size slide

  3. Respect the user’s
    and

    View full-size slide

  4. Smartphone hardware varies
    CPU
    Memory
    Storage
    Screen
    Battery

    View full-size slide

  5. The Performance Gap On Mobile
    src: IHS Markit Smartphone Model Market Tracker 2019H + Geekbench V4

    View full-size slide

  6. If you want to build a fast site,
    use slow hardware

    View full-size slide

  7. The Performance Gap On Desktop
    src: Amazon (bit.ly/bestsellinglaptops - November, 2019) + Geekbench V5, @addyosmani
    Highest selling
    laptops on
    Amazon (2019)
    CPU performance using Geekbench 5

    View full-size slide

  8. Do we need to deliver the
    exact same experience to
    every user?

    View full-size slide

  9. Adaptive Loading

    View full-size slide

  10. Demo
    Open demo

    View full-size slide

  11. Fine-tune Data Transfer
    Use less bandwidth on
    slow connections
    Respect Data Saver
    preferences
    Reduce memory use on
    low-cost devices
    Optimize loading of
    memory-intensive
    resources
    Toggle memory-intensive
    animations
    Limit costly JavaScript on
    low-end devices
    Avoid loading CPU-heavy
    components
    Reduce CPU-intensive
    code execution
    Network Memory CPU

    View full-size slide

  12. Adaptive Loading
    React Hooks
    bit.ly/react-adaptive
    Experimental

    View full-size slide

  13. Adaptive Loading
    bit.ly/adaptive-angular
    Community
    bit.ly/adaptive-vue

    View full-size slide

  14. Home Products Product
    Item Component media
    Fast
    Adaptive Media Loading
    Slow Median
    Connection:

    View full-size slide

  15. const network = navigator.connection.effectiveType;
    console.log ("Effective connection type is " + network); // 3g
    Network-aware Resource Loading
    import { useNetworkStatus } from './network';
    const { effectiveConnectionType } = useNetworkStatus();
    ...
    switch(effectiveConnectionType) {
    case '3g':
    media = ; break;
    case '4g':
    media = ;
    break;

    View full-size slide

  16. Demo
    Open demo

    View full-size slide

  17. const saveData = navigator.connection.saveData;
    if (saveData) { // Don’t load heavy resources }
    Data-Saver aware Resource Loading
    import { useSaveData } from './save-data';
    const { saveData } = useSaveData();
    ...
    return (

    { saveData ? : }

    View full-size slide

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

    View full-size slide

  19. Demo
    Open demo
    WPT

    View full-size slide

  20. .image {
    background-image: url("original.webp");
    }
    @media (prefers-reduced-data: reduce) {
    /* Save-Data: On */
    .image {
    background-image: url("compressed.webp");
    }
    }
    `prefers-reduced-data`
    bit.ly/csswg-prd
    Proposal

    View full-size slide

  21. const memory = navigator.deviceMemory
    console.log ("Device has at least " + memory + "GB of RAM.")
    // Device has at least 4GB of RAM
    Memory-aware Resource Loading
    import { useMemoryStatus } from './memory';
    const { deviceMemory } = useMemoryStatus();
    ...
    return (

    { deviceMemory < 4 ? : }

    View full-size slide

  22. Demo
    Open demo

    View full-size slide

  23. Page Request
    Check Device Class &
    Network
    Module Server responds
    zoom.js related.js
    cart.js
    “Lite” core experience for everyone High-end only features
    Adaptive Module Serving - The Future?
    vendor.js
    magnifier.js modal.js
    ui_library.js utilities.js
    /product-page
    product.js videos.js
    AR.js

    View full-size slide

  24. Home Products Product
    Item Component
    Image Viewer
    Zoom
    Carousel
    Image Viewer
    Low-end device High-end device
    Adaptive Code-splitting & Code-loading
    Core experience

    View full-size slide

  25. import React, { Suspense } from 'react';
    const Sample = React.lazy(() => import('./Sample'));
    function MyComponent() {
    return (

    Loading...}>



    );
    }
    React.lazy() and Suspense

    View full-size slide

  26. Network-aware Code-splitting
    import React, { Suspense } from 'react';
    const myComponent = React.lazy(() => {
    return new Promise(resolve => {
    navigator.connection ? resolve(navigator.connection.effectiveType) :
    resolve(null)
    }).then((effectiveType) => {
    switch (effectiveType) {
    case "3g":
    return import(/* webpackChunkName: "light" */ "./Light.js"); break;
    case "4g":
    return import(/* webpackChunkName: "heavy" */ "./Full.js"); break;

    View full-size slide

  27. Adaptive
    Serving
    Fast? Lazy-load more
    features, like zooming.
    Slow? Just load the
    core experience
    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.

    View full-size slide

  28. Demo
    Open demo

    View full-size slide

  29. const cores = window.navigator.hardwareConcurrency
    console.log ("# logical processor cores are " + cores) // 4
    CPU Core-aware Resource Loading
    import { useHardwareConcurrency } from './hardware-concurrency';
    const { numberOfLogicalProcessors } = useHardwareConcurrency();
    return (
    { numberOfLogicalProcessors <= 4 ?
    : }

    View full-size slide

  30. Home Products Product
    Fast connection
    Slow connection
    Adaptive Data-fetching & Pre-fetching
    GraphQL server
    Database Database Database
    5 results 25 results

    View full-size slide

  31. Disable video autoplay on slow networks
    Only prefetch in-viewport links on 4G
    if (!isOKConnection() || isDataSavingMode()) {
    // don't prefetch visible routes
    return;
    }
    Limit carousel image loads
    on Data Saver / 3G

    View full-size slide

  32. High-end
    Low-end
    Adaptive Capability Toggling
    Static
    Low frame-rate animation
    Full-fidelity animation
    High frame-rate

    View full-size slide

  33. Client Server
    Request client sends current Client Hints
    Adaptive Delivery with Client Hints
    Subsequent requests
    Accept-CH: Device-Memory,Save-Data,Viewport-Width
    Device-Memory: 4
    Viewport-Width: 320
    Save-Data: 1
    content="Device-Memory, Viewport-Width,
    Save-Data">
    Enable
    Added
    Response

    View full-size slide

  34. Demo
    Open demo

    View full-size slide

  35. User Agent String
    “Moto G4” “Single-core score: 684”
    Device Class Detection
    Device Name Detection Service
    RAM
    Device Class
    “Low-end”
    Geekbench CPU benchmarks
    Cores CPU score

    View full-size slide

  36. Do not just respond based on screen size,
    adapt based on actual device hardware

    View full-size slide

  37. Web device classification at Facebook

    View full-size slide

  38. Web device classification at Facebook
    Define buckets

    View full-size slide

  39. Web device classification at Facebook
    Define buckets
    Integrate buckets into logging

    View full-size slide

  40. Web device classification at Facebook
    Define buckets
    Integrate buckets into logging
    Adapt loading based on buckets

    View full-size slide

  41. On mobile we get the device name in the UA,
    so we can use the year class concept.
    Grouping Hardware On Mobile

    View full-size slide

  42. “Mozilla/5.0 (Linux; Android 10; SM-G955U) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0
    Chrome/79.0.0.0 Mobile Safari/537.36”
    “Mozilla/5.0 (Linux; Android 9; Pixel 3 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.0.0 Mobile
    Safari/537.36”
    Mobile UserAgents tell us what the device is

    View full-size slide

  43. “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.0.0
    Safari/537.36”
    “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.0.0
    Safari/537.36”
    On desktop things aren’t so obvious...

    View full-size slide

  44. • UA tells us OS, but not much else
    • What do we have?
    ○ Most desktop browsers have:
    navigator.hardwareConcurrency
    ○ Many desktop browsers have:
    navigator.deviceMemory
    Grouping
    Hardware on
    Desktop

    View full-size slide

  45. Creating desktop
    hardware buckets

    View full-size slide

  46. 1) Log hardwareConcurrency and deviceMemory

    View full-size slide

  47. 1) Log hardwareConcurrency and deviceMemory
    2) Group by hardwareConcurrency, deviceMemory
    and OS when looking at perf data

    View full-size slide

  48. 1) Log hardwareConcurrency and deviceMemory
    2) Group by hardwareConcurrency, deviceMemory
    and OS when looking at perf data

    View full-size slide

  49. 1) Log hardwareConcurrency and deviceMemory
    2) Group by hardwareConcurrency, deviceMemory
    and OS when looking at perf data
    3) Figure out buckets based on groupings

    View full-size slide

  50. When integrated
    into performance
    logging, hardware
    class reveals a more
    complete picture

    View full-size slide

  51. Adaptivity should be
    considered in your core
    frameworks

    View full-size slide

  52. Think about animations
    Low End
    High End

    View full-size slide

  53. Mobile Websites

    View full-size slide

  54. Load fast vs respond fast

    View full-size slide

  55. if (isLowEndDevice()) {
    scheduler.unstable_forceFrameRate(15);
    }

    View full-size slide

  56. isInputPending

    View full-size slide

  57. Using consistent definitions
    for buckets in logging and
    adapting lets you easily see
    the full picture

    View full-size slide

  58. Adaptive Loading
    Serve low-quality images & videos
    Conditionally load heavier JS on fast devices
    Avoid computationally heavy operations
    Turn off or throttle Animations
    Block 3rd-party scripts on slower devices

    View full-size slide

  59. Make your site Lazy-First
    Reduce
    Defer
    Coalesce

    View full-size slide

  60. Design your site with
    inclusivity in mind

    View full-size slide

  61. Thank you!
    Addy Osmani
    Chrome
    @addyosmani
    Nate Schloss
    Facebook
    @n8schloss
    With special thanks to Anton Karlovskiy

    View full-size slide