Dev Tips: Only download JavaScript when it is appropriate

Dev Tips


Hey everyone! I have a different sort of tip for you today, hope it's useful.
 

JavaScript: Conditional JavaScript, only download when it is appropriate


Intro

In this post, I'd like to share a few techniques which you can use for selectively downloading/executing resources such as JavaScript.

As an example, if the users device does not have a lot a RAM, you could decide to skip the downloading (and in turn, the parse + execution costs) of a particular JavaScript resource.

Note: I won't be specifying the exact times you should minimise usage of JavaScript. It ultimately depends on your use case.

  • If I were building a game in WebGL, I'd probably load files regardless of navigator.deviceMemory.
  • If I were building Wikipedia, I might indeed skip loading of some JavaScript based on navigator.deviceMemory + navigator.getBattery() + navigator.connection.downlink.


Load JavaScript if the device has enough RAM

Let's start out with this:

if (navigator.deviceMemory > 1) {
    await import('./costly-module.js');
}
Getting the device memory from JavaScript

Browser support is limited to Chromium based browsers, which according to caniuse is 70% of the global usage stats. If navigator.deviceMemory is undefined, maybe consider loading the JavaScript regardless.

Detecting device memory on the server

The Web Platform is full of hidden features. Turns out you can get this information on your server!

Getting the device memory from a network request header

The browser can send a network request header which means your server can decide on the most appropriate resource to send back down. Use this <meta> tag in your HTML to activate this feature:

<meta http-equiv="Accept-CH" content="Device-Memory">


Load JavaScript when the device has enough CPU

You can get the number of logical processors on the users device with hardwareConcurrency.

if (navigator.hardwareConcurrency > 4) {
    await import('./costly-module.js');
}

MDN has an explanation:

 

The number of logical processor cores can be used to measure the number of threads which can effectively be run at once without them having to context switch.

Logical processors

This feature can be especially useful when creating new Workers - part of the Web Workers API.

Browser support is very good.


Load JavaScript when the user has enough battery left

We've all been there. Low battery 🔋️, no charger, and you start clearing apps in the hope that your 4% lasts on the journey home.

A page with JavaScript will utilise more battery than a page without JavaScript - and yes, the same applies to CSS and images.

The Network Download, Parse and Execution costs will defintely use battery, but don't forget the variety of tasks which JavaScript is capable of e.g. creating long-running timers.

// { level: 0.53 (53%), charging: true...}
const {level, charging} = await navigator.getBattery();

// If the device is currently charging
// Or the battery level is more than 20%
if (charging || level > 0.2) {
        await import('./costly-module.js');
}

You also get charging times and discharging times which in some scenarios could be even more valuable than what the current level is.

Battery Status

Browser support seems to be limited to Chromium based browsers. Interestingly it was removed in Firefox due to privacy concerns (a.k.a. fingerprinting 🖐🏼️).


Load JavaScript when the device has enough storage

This one really depends on what the JavaScript is doing. For example if the JavaScript is:

  • Downloading lots of maps as part of a game.
  • Downloading + Saving website resources via a Service Worker (e.g. for offline capabilities).
  • Downloading large textures/assets part of a visualisation.

Then maybe consider the idea of using storage availability to influence downloading of resources.

const {quota} = await navigator.storage.estimate();
const fiftyMegabytesInBytes = 50 * 1e+6;

if (quota > fiftyMegabytesInBytes) {
    await import('./costly-module.js');
}

Browser support is decent

Storage quota


Load JavaScript when the device has a good network connection

At this point, you can argue it's also effective to skip the download of any optional resource - not just JavaScript.

// ⚠️ 4g does not mean fast!
if (navigator.connection.effectiveType === '4g') {
    await import('./costly-module.js');
}

The navigator.connection object gives some information on the network. E.g. the downlink property gives you the bandwidth in megabits per second. The round-trip time is in milliseconds

Network Info

How you use this API is highly dependant on your use case. But as an example, if navigator.connection.downlink is low, you can download smaller resources instead. In an ideal scenario, this setting would be customisable however (via your webpage UI).

Note: Being on WiFi doesn't mean fast, and being on 3G doesn't mean slow. For example, think about tethering!

Browser support seems to be limited to Chromium based browsers.

Getting the network information on the server

You can also get some of that network information on your server, in the form of a network request header.

Network downlink as a request header

To achieve this, use the following <meta> tag in your main HTML file:

<meta http-equiv="Accept-CH" content="Downlink">

Subsequent requests now have the request header: downlink: 6 for example. You can also use content="ECT" to get the Effective Connection Type as a network request header.

Save-data

While you can infer context based on network information like roundtrip times and connection types, the saveData property states a device preference for reduced data usage.

if (navigator.connection.saveData === false) {
    await import('./costly-module.js');
}

This is available server side (as a client hint), and at some point it should be available as a CSS Media Feature.


Conclusion

It's not all about JavaScript, you can also use these various device details to:

  • Reduce heavy/complex animations - which can be a challenge for devices with low memory.
  • Reduce the download of heavily encoded images (e.g. AVIF) - which can be a battery drain.
  • Reduce download of network resources of any type - which can struggle on a congested network connection.

If you have any troubles viewing this animated gif, check out: umaar.com/dev-tips/242-considerate-javascript
Email Marketing Powered by Mailchimp

Copyright © 2020 Umar, All rights reserved.
You are receiving this email because you signed up for Dev Tips.

unsubscribe from this list    update subscription preferences 

Older messages

Dev Tips: DevTools: Record tests with the puppeteer recorder

Friday, December 4, 2020

A test generator for puppeteer built into Canary DevTools Dev Tips DevTools: Record tests with the puppeteer recorder 🎥️ Introduction The Puppeteer Recorder feature in Chrome DevTools can monitor your

Dev Tips: DevTools: Refactor your styles with CSS Overview

Wednesday, November 18, 2020

View different metrics on your styles and improve your overall CSS architecture Dev Tips DevTools: Refactor your stylesheets with CSS Overview Introduction The CSS Overview Panel provides interesting

Dev Tips: DevTools: Create your own keyboard shortcuts  ⌨️

Friday, November 13, 2020

The Shortcut Editor lets you assign your own preferred keyboard shortcuts to common workflows. Dev Tips DevTools: Create your own keyboard shortcuts ⌨️ Introduction The DevTools Shortcut Editor lets

Dev Tips: DevTools: The New Media Panel  🎬

Wednesday, November 4, 2020

The Media Panel in DevTools provides useful video inspection tools, useful for debugging, understanding, and learning about video. Dev Tips DevTools: The New Media Panel 🎬 I've written an article

Dev Tips: DevTools: CSS Grid Inspection ✨

Wednesday, October 28, 2020

Dev Tips DevTools: CSS Grid Inspection ✨ Hey everyone! I took a little break, but I'm back and I've got some great tips to share with you over the next few weeks! Introduction CSS Grid

You Might Also Like

📧 Did you watch the FREE chapter of Pragmatic REST APIs?

Friday, February 28, 2025

​ Hey, it's Milan. 👋 The weekend is almost upon us. So, if you're up for some quality learning, consider watching the free chapter of Pragmatic REST APIs. Scroll down to the curriculum or click

Data Science Weekly - Issue 588

Thursday, February 27, 2025

Curated news, articles and jobs related to Data Science, AI, & Machine Learning ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏

💎 Issue 458 - Why Ruby on Rails still matters

Thursday, February 27, 2025

This week's Awesome Ruby Newsletter Read this email on the Web The Awesome Ruby Newsletter Issue » 458 Release Date Feb 27, 2025 Your weekly report of the most popular Ruby news, articles and

📱 Issue 452 - Three questions about Apple, encryption, and the U.K

Thursday, February 27, 2025

This week's Awesome iOS Weekly Read this email on the Web The Awesome iOS Weekly Issue » 452 Release Date Feb 27, 2025 Your weekly report of the most popular iOS news, articles and projects Popular

💻 Issue 451 - .NET 10 Preview 1 is now available!

Thursday, February 27, 2025

This week's Awesome .NET Weekly Read this email on the Web The Awesome .NET Weekly Issue » 451 Release Date Feb 27, 2025 Your weekly report of the most popular .NET news, articles and projects

💻 Issue 458 - Full Stack Security Essentials: Preventing CSRF, Clickjacking, and Ensuring Content Integrity in JavaScript

Thursday, February 27, 2025

This week's Awesome Node.js Weekly Read this email on the Web The Awesome Node.js Weekly Issue » 458 Release Date Feb 27, 2025 Your weekly report of the most popular Node.js news, articles and

💻 Issue 458 - TypeScript types can run DOOM

Thursday, February 27, 2025

This week's Awesome JavaScript Weekly Read this email on the Web The Awesome JavaScript Weekly Issue » 458 Release Date Feb 27, 2025 Your weekly report of the most popular JavaScript news, articles

💻 Issue 453 - Linus Torvalds Clearly Lays Out Linux Maintainer Roles Around Rust Code

Thursday, February 27, 2025

This week's Awesome Rust Weekly Read this email on the Web The Awesome Rust Weekly Issue » 453 Release Date Feb 27, 2025 Your weekly report of the most popular Rust news, articles and projects

💻 Issue 376 - Top 10 React Libraries/Frameworks for 2025 🚀

Thursday, February 27, 2025

This week's Awesome React Weekly Read this email on the Web The Awesome React Weekly Issue » 376 Release Date Feb 27, 2025 Your weekly report of the most popular React news, articles and projects

February 27th 2025

Thursday, February 27, 2025

Curated news all about PHP. Here's the latest edition Is this email not displaying correctly? View it in your browser. PHP Weekly 27th February 2025 Hi everyone, Laravel 12 is finally released, and