loading...
Cover image for Adaptive Loading - Improving Web Performance on low-end devices

Adaptive Loading - Improving Web Performance on low-end devices

addyosmani profile image Addy Osmani Originally published at addyosmani.com Updated on ・3 min read

Adaptive Loading: Do not just respond based on screen size, 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? 🤔

In our Chrome Dev Summit talk, Facebook's Nate Schloss and I talk about Adaptive Loading - this pattern ...

  • Delivers a fast core experience to all users (including low-end devices)
  • Progressively adds high-end-only features, if a user's network and hardware can handle it.

This allows users to get an experience best suited to their constraints.

The use-cases adaptive loading unlocks include:

  • Serving low-quality images & videos on slow networks
  • Loading non-critical JavaScript for interactivity only on fast CPUs
  • Throttling the frame-rate of Animations on low-end devices
  • Avoiding computationally heavy operations on low-end devices
  • Block 3rd-party scripts on slower devices

There are a number of signals we can use for Adaptive Loading, including:

In our talk, we cover real-world examples of these ideas being used in sites such as Facebook, eBay, Tinder and others. Check out 24mins in where Nate walks through how Facebook uses some of these ideas in production, via device grouping:

We also released a new (experimental) set of React Hooks & Utilities for adding adaptive-loading techniques to your React apps.

GitHub logo GoogleChromeLabs / react-adaptive-hooks

Deliver experiences best suited to a user's device and network constraints

React Adaptive Loading Hooks & Utilities · Build Status npm bundle size

Deliver experiences best suited to a user's device and network constraints (experimental)

This is a suite of React Hooks and utilities for adaptive loading based on a user's:

It can be used to add patterns for adaptive resource loading, data-fetching, code-splitting and capability toggling.

Objective

Make it easier to target low-end devices while progressively adding high-end-only features on top. Using these hooks and utilities can help you give users a great experience best suited to their device and network constraints.

Installation

npm i react-adaptive-hooks --save or yarn add react-adaptive-hooks

Usage

You can import the hooks you wish to use as follows:

import { useNetworkStatus } from 'react-adaptive-hooks/network';
import { useSaveData } from 'react-adaptive-hooks/save-data';
import { useHardwareConcurrency } from 'react-adaptive-hooks/hardware-concurrency';
import { useMemoryStatus } from

Our hooks/utilities include the useNetworkStatus React hook for adapting based on network status (effective connection type):

import React from 'react';

import { useNetworkStatus } from 'react-adaptive-hooks/network';

const MyComponent = () => {
  const { effectiveConnectionType } = useNetworkStatus();

  let media;
  switch(effectiveConnectionType) {
    case '2g':
      media = <img src='medium-res.jpg'/>;
      break;
    case '3g':
      media = <img src='high-res.jpg'/>;
      break;
    case '4g':
      media = <video muted controls>...</video>;
      break;
    default:
      media = <video muted controls>...</video>;
      break;
  }

  return <div>{media}</div>;
};

The useSaveData utility for adapting based on the user's browser Data Saver preferences:

import React from 'react';

import { useSaveData } from 'react-adaptive-hooks/save-data';

const MyComponent = () => {
  const { saveData } = useSaveData();
  return (
    <div>
      { saveData ? <img src='...' /> : <video muted controls>...</video> }
    </div>
  );
};

...and the useHardwareConcurrency utility for adapting based on the number of logical CPU processor cores on the user's device:

import React from 'react';

import { useHardwareConcurrency } from 'react-adaptive-hooks/hardware-concurrency';

const MyComponent = () => {
  const { numberOfLogicalProcessors } = useHardwareConcurrency();
  return (
    <div>
      { numberOfLogicalProcessors <= 4 ? <img src='...' /> : <video muted controls>...</video> }
    </div>
  );
};

In the future, we hope to see more examples of infrastructure that can automatically deliver the most optimal bundles of code based on a user's network & device constraints. Between Client Hints and the client-side APIs used above, the building blocks to build something compelling in this space may already exist :)

We hope you'll find Adaptive Loading an interesting addition to your Progressive Enhancement toolbox. Check out our talk to learn more :)

Read more:

Discussion

pic
Editor guide
Collapse
ben profile image
Ben Halpern

This is fabulous. As soon as we start using any of these adaptive loading signals I can't wait to make a post about it.

Collapse
addyosmani profile image
Addy Osmani Author

Ooh! Thanks, Ben! Excited to hear about dev.to using any of these signals :)

One silly idea to start experimenting could be serving even more highly compressed header images if a user is on a slower network connection or has Data Saver turned on 🤓

Collapse
256hz profile image
Abe Dolinger

This solution makes me want to have this problem!

Collapse
kawhyte profile image
Kenny Whyte

Great post Addy! I saw this presentation live at the Dev summit. It was very informative.

Collapse
addyosmani profile image
Addy Osmani Author

Thank you, Kenny!

Collapse
thepeoplesbourgeois profile image
Josh

Before degrading your feature set for lower-end devices, remember to leverage web workers and handleEvent

Collapse
nydame profile image
Felicia Betancourt

This is certainly an exciting development. One question though: is this a departure from Google's drive to Accelerated Mobile Pages (AMP)? It is striking that you didn't mention it even once.

Collapse
addyosmani profile image
Addy Osmani Author

As I work on Chrome, I tend to focus on more general web performance guidance vs. AMP, but these patterns could very much be used with it :) I recently saw a site that would load their AMP experience as the "light" version if they detected a user was on a slow network connection.

Collapse
renesansz profile image
Rene Padillo 🇵🇭

amazing! This is nice!

I hope this would be included in the HTML standard in the future just like how we adapted the media standard for pictures!

Collapse
kp profile image
KP

@addyosmani this is amazing...and I love your talk. Does something like this exist for the Vue.js ecosystem?

Collapse
nickytonline profile image
Nick Taylor (he/him)

Awesome sauce. I checked out the react-adaptive-hooks repo the other day, but haven't had a chance to watch your talk yet. Definitely on my what to watch next list.

Thanks for sharing Addy!

Collapse
addyosmani profile image
Addy Osmani Author

Cheers, Nick! If you end up trying out react-adaptive-hooks, I'd love to hear any feedback you have on it :)

Collapse
aligoren profile image
Ali GOREN

Thanks. I think this will help. As a full-stack, I never thought about low-end devices. Thanks again. I understand now why our clients leave us :)

Collapse
blacksonic profile image
Gábor Soós

Good to see more and more well-known people publishing here. I've already came accross it on Twitter, good article as always.

Collapse
tmamedbekov profile image
Tony Mamedbekov

This is a great article thank you Addy. So now the trend is moving from Headless to Adaptive Architecture. Love it.