Make your website fast for the low-end with adaptive loading
Tldr;
In this post, I introduce you to adaptive loading. Adaptive loading is a pattern where your website responds to the user based on their actual device and network connection.
What is Adaptive Loading?
Adaptive loading is a pattern where your website responds to users based on their actual device and network connection.
Device capabilities and network conditions vary a lot in our world. Depending on your location, mobile phone, or cellular contract, you can have different experiences.
For 2019 North America was the most expensive country to purchase for a smartphone. The average price was about 480 Euros. 100 Euro more than in Europe, and in the Middle East or Africa, a smartphone even cost 230 Euros on average.
These statistics mean that many people have low-end devices. Adaptive loading is improving web performance on slow devices. Your website might make users with high-end devices happy while others can not use your site. With adaptive loading, you can deliver a fast experience to all users.
What are the use cases?
- Serving low-quality images or videos on slow networks or if the user has low memory.
- Throttle the frame-rate on low-end devices
- Serve uncritical resources only on high-end devices
- Block third-party scripts on slow devices
- Adaptive Prefetching or Adaptive Delivery with Client Hints.
How does Adaptive Loading work?
Adaptive loading accesses the user’s device and delivers your website depending on three properties: the network condition, the memory usage, and the CPU core count.
- Network conditions via navigator.connection.effectiveType. You can also use the Data Saver preferences via navigator.connection.saveData.
- Memory status via navigator.deviceMemory.
- CPU core count via navigator.hardwareConcurrency.
These three methods give you the possibility of the client. You could also do this on the server with client hints.
Adaptive Media Loading
On a low-end device, you don’t need to serve a high-quality image or video. You could measure the network condition and memory consumption before serving a low- or high-quality image.
Use cases for Adaptive Media Loading
- Serve a slider only to high-end devices
- Deliver fewer results at one time
- Request fewer media items from API
Newsletter
Hello and welcome! Don't miss out on crucial web performance insights, plus the latest on accessibility and sustainability, delivered directly to your inbox. Elevate your craft in creating fast, user-friendly, and eco-conscious websites. Sign up now to access seasoned expertise and the freshest news!
Adaptive Code-Splitting & Code Loading
Adaptive Code-Splitting is about shipping a light bundle to users with fewer CPU cores, a slow network, or less memory. For high-end devices, you can add additional features on top. You can even load more on high-end devices to engage your user to stay on your website.
Adaptive data-fetching and pre-fetching
If you are sending less data, it results in less network traffic, less memory usage, and less CPU. You can access device properties to determine if you send fewer data to the user. Additionally, you can reduce the number of websites that your application prefetches.
Implement Adaptive Loading
Implementing Adaptive Loading is easy to do. The API you use is well documented and has excellent examples.
Network
The Network Information API provides information about the connection and has the following properties.
Property | Explanation |
---|---|
downlink | The bandwidth estimate in megabits per second. |
effectiveType | effectiveType The effective type of the connection, with possible values ‘slow-2g’, ‘2g’, ‘3g’, or ‘4g’ (covers 4g and higher). |
onchange | An event handler that fires when connection information changes. |
rtt | The estimated round-trip latency of the connection in milliseconds. |
saveData | A boolean that defines whether the user has requested a reduced data usage mode. |
Examples
Detect connection changes
var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
var type = connection.effectiveType;
function updateConnectionStatus() {
console.log("Connection type changed from " + type + " to " + connection.effectiveType);
type = connection.effectiveType;
}
connection.addEventListener('change', updateConnectionStatus);
Detect connection
let preloadVideo = true;
var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
if (connection) {
if (connection.effectiveType === 'slow-2g') {
preloadVideo = false;
}
}
Detecting the Save-Data setting
if ("connection" in navigator) {
if (navigator.connection.saveData === true) {
// Implement data saving operations here.
}
}
Detecting device memory
const memory = navigator.deviceMemory
console.log (`This device has at least ${memory}GiB of RAM.`)
Detecting the number of logical processors
var logicalProcessors = window.navigator.hardwareConcurrency
Conclusion
In this post, I explained the pattern of adaptive loading. I outlined the main parts and showed you implementation examples.
If you like this article, smile for a moment, share it, follow me, check out my RSS feed, and subscribe to my newsletter.
Cheers Marc
Further Reading
- Adaptive Loading - Improving web performance on low-end devices
- Adaptive Loading - Improving web performance on slow devices (Chrome Dev Summit 2019)