Web Storage



Good day, friends.

I present to you the translation of the article “Storage for the Web” by Pete LePage.

There are several technologies for storing data in a browser. Which one is better?

An internet connection may be poor or even absent in certain places. Therefore, offline support is one of the key features of progressive web applications . Even with a high-speed connection, it’s prudent to use caching and other techniques to improve the user experience. There are several ways to save files (HTML, JavaScript, CSS, images, etc.) and data (user data, news articles, etc.). But which solution is better to choose? And how to ensure its durability?

What to use?


I can advise the following:


IndexedDB and Cache API are supported by all modern browsers. They are asynchronous, i.e. Do not block the main thread (code execution). They are available at the Window object, web workers, and service workers. In other words, they can be used everywhere.

What about other mechanisms?


The browser also has other data storage mechanisms, but they have certain limitations and can lead to performance problems.


?


At least a few hundred megabytes, potentially hundreds of gigabytes. It depends on the browser, however, the amount of storage is usually based on the amount of available memory in the user's device.

  • Chrome allows you to use up to 60% of disk space. You can use the StorageManager API to determine the limit (quota).
  • Internet Explorer 10 and later can store up to 250 MB of data.
  • Firefox allows you to store up to 2 GB of data. You can use the StorageManager API to determine the limit.
  • Safari (both desktop and mobile) allows you to store up to 1 GB of data. Upon reaching the limit, Safari asks the user for permission to increase the quota by 200 MB.

In the past, when the storage limit was reached, browsers requested user permission to increase the amount of memory. For example, when a limit of 50 MB is reached, the browser requested user permission to increase the quota to 100 MB, and so every 50 MB.

Today, most browsers do not, automatically increasing the amount of storage within the quota. The exception is Safari, which, upon reaching 750 MB, asks for user permission to increase the limit to 1.1 GB. An attempt to exceed the quota will end in failure.

How to check the balance of the limit?


For this, in many browsers, you can use the StorageManager API. It shows the total number of bytes used by IndexedDB and the Cache API, allowing you to calculate the remainder.

if(navigator.storage && navigator.storage.estimate) {
  const quota = await navigator.storage.estimate()
  // quota.usage ->   
  // quota.quota ->   
  const percentageUsed = (quota.usage / quota.quota) * 100
  console.log(`  ${ percentageUsed}% `)
  const remaining = quota.quota - quota.usage
  console.log(`   ${remaining} `)
}

Please note that the StorageManager API is not yet supported by all browsers. However, even if it is supported, an error handler must be provided. In some cases, the quota may exceed the actual storage capacity.

Inspection


During development, you can use browser tools to track the status of various repositories and clean them up.



While working on this article, I wrote this simple tool for quick testing of storage capabilities. This is a quick and easy way to experiment with different storage mechanisms and see what happens when the quota is exceeded.

How to handle errors?


What to do when the limit is reached? Of course, handle errors, be it QuotaExceededError or something else. Then, depending on the design of your application, you should choose the way they are processed. You can, for example, delete old content or data depending on their size, or provide the user with the ability to decide what to delete.

IndexedDB and the Cache API throw a DOMError QuotaExceededError when a quota is exceeded.

Indexeddb


When the limit is reached, an attempt to write data to IndexedDB will fail. The onabort () method will be called with the event as an argument. The event will contain a DOMException in the error property. Checking the error name will return a QuotaExceededError.

const transaction = idb.transaction(['entries'], 'readwrite')
transaction.onabort = function(event) {
    const error = event.target.error // DOMException
    if(error.name === 'QuotaExceededError') {
        // ...
    }
}

Cache API


An attempt to write data to the Cache API when the limit is reached will be rejected with a QuotaExceededError DOMException.

try {
    const cache = await caches.open('my-cache')
    await cache.add(new Request('/sample1.jpg'))
} catch (error) {
    if(error.name = 'QuotaExceededError') {
        // ...
    }
}

How does storage cleanup work?


Web repositories fall into two categories, “stand-alone” and “managed”. Stand-alone means that the repository can be cleared by the browser without user intervention, however it is less adaptable for prolonged use, as well as in the presence of critical data. Managed vaults are not automatically cleaned when full. The user must manually clear such storages (through browser settings).

By default, web storages (IndexedDB, Cache API, etc.) are classified as stand-alone, which means that if manual control is not installed , the browser can independently clear the storage under certain conditions, for example, when filling.

The conditions for cleaning the storage are as follows:

  • When the storage is full, Chrome deletes data, starting with the least requested (the oldest in use time), until the overflow problem is resolved.
  • IE 10+ does not clear the storage, but blocks the ability to write data.
  • Firefox does the same thing as Chrome.
  • Safari did not previously empty the vault, but recently added a seven-day data retention period.

Starting with iOS and iPad 13.4, Safari 13.1 on macOS, there is a seven-day data retention period. This means that if the user does not access the data within seven days, they will be deleted. This policy does not apply to applications added to the home screen.

Bonus: Promise Wrap Over IndexedDB


IndexedDB is a low-level API that requires some configuration before use, which may be unnecessary if you need to store simple data. Unlike most modern Promise-based APIs, it is event-based. A wrapper from promises, such as idb, hides some powerful features of this repository, but, more importantly, it also hides its complex internal mechanisms (transactions, versioning).

Conclusion


Times of limited storage and user permission requests to increase the limit have sunk into oblivion. Sites can effectively store all the resources and data they need to work. Using the StorageManager API, you can determine how much memory is used and how much is left. And by putting the storage in manual control mode, you can protect data from deletion.

Note per .:

  • Here you can see how to write an application for notes using idb.
  • Here you can see how service workers work.

Thank you for your time. I hope it was well spent.

All Articles