Adaptive Loading - Improving Web Performance on low-end devices
Tags: webperf, webdev, react, network
Published: 2019-11-18 19:56:47

---
title: Adaptive Loading - Improving Web Performance on low-end devices
published: true
description: Adaptive Loading is a pattern for delivering a fast core experience to all users (including low-end devices) where you progressively add high-end-only features, if a user's network and hardware can handle it
tags: webperf, webdev, react, network
cover_image: https://thepracticaldev.s3.amazonaws.com/i/k4d718bv7a9p1bnp6daq.png
canonical_url: https://addyosmani.com/blog/adaptive-loading/
---

*[Adaptive Loading](https://www.youtube.com/watch?v=puUPpVrIRkc): 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](https://v8.dev/blog/cost-of-javascript-2019) 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](https://www.youtube.com/watch?v=puUPpVrIRkc), 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.

{% youtube puUPpVrIRkc %}

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

![](https://thepracticaldev.s3.amazonaws.com/i/f9jc248z5x8sw1q78z0o.png)

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

* **Network** - for fine-tuning data transfer to use less bandwidth (via [`navigator.connection.effectiveType`](https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API)). We can also leverage the user's Data Saver preferences (via [`navigator.connection.saveData`](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/save-data#detecting_the_save-data_setting))
* **Memory** - for reducing memory consumption on low-end devices (via [`navigator.deviceMemory`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory))
* **CPU core count** - for limiting costly JavaScript execution and reducing CPU intensive logic when a device can't handle it well (via [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorConcurrentHardware/hardwareConcurrency)). This is because JavaScript execution is [CPU bound](https://www.youtube.com/watch?v=puUPpVrIRkc).

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](https://youtu.be/puUPpVrIRkc?t=1443) where Nate walks through how Facebook uses some of these ideas in production, via device grouping:

![](https://thepracticaldev.s3.amazonaws.com/i/lg8rav4vuqv7lu2ce38o.jpg)

We also released a new (experimental) set of [React Hooks & Utilities](https://github.com/GoogleChromeLabs/react-adaptive-hooks) for adding adaptive-loading techniques to your React apps. 

{% github googlechromelabs/react-adaptive-hooks %}


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

```js
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:

```js
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:

```js
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](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/client-hints) and the client-side APIs used above, the building blocks to build something compelling in this space may already exist :)

![](https://thepracticaldev.s3.amazonaws.com/i/1m81metyh0c549lt4xc5.jpg)

We hope you'll find Adaptive Loading an interesting addition to your Progressive Enhancement toolbox. Check out our [talk](https://www.youtube.com/watch?v=puUPpVrIRkc) to learn more :)

Read more:

* [React Adaptive Loading hooks and utilities](https://github.com/GoogleChromeLabs/react-adaptive-hooks)
* [Sophisticated Adaptive Loading Strategies](https://medium.com/@roderickhsiao/sophisticated-adaptive-loading-strategies-7118341fcf91) from Tinder Web engineering
* [Connection-Aware Components in Angular](https://netbasal.com/connection-aware-components-in-angular-3a66bb0bab6f)
* [Serving Adaptive Components Using the Network Information API](https://dev.to/vorillaz/serving-adaptive-components-using-the-network-information-api-lbo) with Vue and Web Components
* [Adaptive serving based on network quality](https://web.dev/adaptive-serving-based-on-network-quality/)