Made in Builder.io

Upcoming webinar with Figma: Design to Code in 80% Less Time

Announcing Visual Copilot - Figma to production in half the time

Builder.io logo
Talk to Us
Platform
Developers
Talk to Us

Blog

Home

Resources

Blog

Forum

Github

Login

Signup

×

Visual CMS

Drag-and-drop visual editor and headless CMS for any tech stack

Theme Studio for Shopify

Build and optimize your Shopify-hosted storefront, no coding required

Resources

Blog

Get StartedLogin

‹ Back to blog

WEB APIS

Web APIs for smooth resource intensive apps

March 22, 2023

Written By Manu Mtz.-Almeida

For decades developers that have been building resource intensive apps and games had to think about how their products would work in older devices.

Triple-A games like Call of Duty allow their users to customize the graphics quality level. You might have seen games running on "Max Settings" with some $1000 GPU card, which is amazing, but most likely it would fry your computer and not even work.

An image of a burning laptop.

When building complex apps or games for the web, we face the same problem. Luckily for us, the web includes very convenient APIs that allow us to know how fast or how much memory the user's machine has, as well as how fast their internet connection is!

The idea is to use these settings to automatically adjust certain levels of quality in your app.

Navigator.hardwareConcurrency

navigator.hardwareConcurrency is a property in the JavaScript Navigator interface that indicates the number of logical processors available on the user's device.

The hardwareConcurrency property is useful for web developers who want to optimize the performance of their web applications by running different parts of the application in parallel. For example, if a web application performs a lot of calculations or intensive tasks, it can use the value of hardwareConcurrency to determine how many threads it can run in parallel to utilize the available resources efficiently.

It's important to note that the value of navigator.hardwareConcurrency is not always accurate, as it depends on the browser implementation and the operating system. Some browsers may return a higher or lower value than the actual number of logical processors available.

const concurrency = navigator.hardwareConcurrency;
let quality;
if (concurrency < 2) {
  quality = 'low';
} else if (concurrency < 4) {
  quality = 'normal';
} else {
  quality = 'high';
}

navigator.deviceMemory is a property that is part of the JavaScript Navigator interface. It provides information about the device's memory in gigabytes (GB).

The deviceMemory property is a read-only property that returns an approximation of the device's total RAM in GB, rounded to the nearest power of 2.

For example, if the device has 4 GB of RAM, navigator.deviceMemory will return 4. If the device has 6 GB of RAM, it will return 8 (which is the nearest power of 2).

Developers can use this property to make decisions about how much memory their web applications should consume or allocate. This can help improve the overall performance of the application by avoiding excessive memory usage, which can slow down the user's device.

It's worth noting that navigator.deviceMemory is not supported by all browsers and platforms. Additionally, the value returned by this property is an approximation and may not be accurate in all cases, however we will not depend on it for a critical part of our app.

Similarly with the previous example, we could use this property to decide an adequate texture quality:

const memory = navigator.deviceMemory;
let textureQuality;
if (memory < 2) {
  textureQuality = 'low';
} else if (memory < 4) {
  textureQuality = 'normal';
} else {
  textureQuality = 'high';
}

One example of using this API in the wild is for determining the resolution of the normal’s map in order to generate shadows in many games. This texture can be extremely big to provide perfectly accurate reflexions, but it can safely be reduced without causing an equivalent drop in visual quality.

Sometimes, it’s not about the raw CPU and memory capabilities, but about the internet connection. It might be a bad idea to make them wait until the 4K textures download.

One API that we can use is navigator.connection, it will provide us with useful information about the internet quality of our user.

const downlink = navigator.connection?.downlink;
const effectiveType = navigator.connection?.effectiveType;

let lowMode = false;
if (effectiveType !== 'wifi') {
  lowMode = true;
}
if (downlink < 5) {
  lowMode = true;
}

This API is highly experimental, but still useful because your application will still work regardless this API is available not.

From the MDN docs, here’s all the information you can get out of NetworkInformation.

  • NetworkInformation.downlink: Returns the effective bandwidth estimate in megabits per second, rounded to the nearest multiple of 25 kilobits per seconds.
  • NetworkInformation.downlinkMax: Returns the maximum downlink speed, in megabits per second (Mbps), for the underlying connection technology.
  • NetworkInformation.effectiveType]: Returns the effective type of the connection meaning one of 'slow-2g', '2g', '3g', or '4g'. This value is determined using a combination of recently observed round-trip time and downlink values.
  • NetworkInformation.rtt: Returns the estimated effective round-trip time of the current connection, rounded to the nearest multiple of 25 milliseconds.
  • NetworkInformation.saveData: Returns true if the user has set a reduced data usage option on the user agent.
  • NetworkInformation.type: Returns the type of connection a device is using to communicate with the network. It will be one of the following values: bluetooth, cellular, ethernet, none, wifi, wimax, other ,unknown.

While this API is not about performance, it’s important to keep it mind, when building very applications with lots of effects and animations. For accessibility reasons, some people can experience extreme discomfort and even epilepsy.

The easiest way to use this API is directly in CSS, using a media query.

@media (prefers-reduced-motion: reduced) {
  .header {
    transition: none;
  }
}

In the example belong, we disable the transition animation of the header, only when the user selected reduced motion.

If you are building stuff in 3D, maybe Three.js, using CSS might not suite you, likely for us, there is a API to evaluate media queries directly from JavaScript: window.matchMedia()

We can use it like this:

const reducedAnimation = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

if (reducedAnimation) {
  disableBigFlashingAnimations();
}

We also wrote a long blog post about other CSS tips that will boost your web skills, check it out!

Introducing Visual Copilot: convert Figma designs to code using your existing components in a single click.

Try Visual Copilot

Share

Twitter
LinkedIn
Facebook
Hand written text that says "A drag and drop headless CMS?"

Introducing Visual Copilot:

A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot
Newsletter

Like our content?

Join Our Newsletter

Continue Reading
AI9 MIN
How to Build AI Products That Don’t Flop
WRITTEN BYSteve Sewell
April 18, 2024
Web Development13 MIN
Convert Figma to Code with AI
WRITTEN BYVishwas Gopinath
April 18, 2024
Web Development8 MIN
Server-only Code in Next.js App Router
WRITTEN BYVishwas Gopinath
April 3, 2024