DEV Community

Cover image for A Guide to Browser-Side Storage
Quokka Labs for Quokka Labs

Posted on

A Guide to Browser-Side Storage

We can manage our data with our preferences on the server and client(browser sides). Be it browser or client-side storage, both have their usability. To manage easy accessibility and persistence from any web browser, it is required to host the database.

Client-side data storage is feasible in various stages:
If you don't want to move the data on the server side and keep it preserved on the client side. It is feasible from practical practice, performance, security, or other loaded reasons.

Suppose you preserve the view or state of any application, its panel, functionalities, or theme data. The browser or client-side storage makes it possible.

Suppose you are working on an offline application and perfectly setup up the initial. It would be acceptable to keep it on localhost or client-side storage.

Client-side storage preserves the data for the active session on temporary storage or until the user removes it.

Know about Old to New-gen preferable client-side storage

Browser-side storage or client-side storage keeps evolving. Developers have tried many options for privacy, security, and performance. Each one has a different storage API and functionality for different states.

Let’s first learn about the older client storage APIs. window.name and WebSQL are the most practiced APIs for browser-side storage. The main reason for prohibiting modern development is the risk of vulnerabilities, hacking, and less compatibility with modern development projects.

Before we talk about the two, let's introduce you to the predecessor of API: AppCache. It provides the caching behavior representation in a plain text manifest file. It is not preferable and standard API because it can take your website at stack. It has some vulnerabilities, gotchas, that completely disturb the loading of no-cached resources. If you are comfortable with its concept and have no risk of taking your app anywhere, then it's preferable.

Window.name

Suppose you're deploying the project's older browser version and have no such sensitive data to keep preserved. In this scenario, it is best to enable session-only temporary data storage. This was commonly popular for the polyfill or hack in IE7. If integrated into another domain window.name will modify.

Additionally, it will require serialization and deserialization.

It accepts the data as follows:
let value = { a:1, b:2, c:3 };
window.name = JSON.stringify( value );

Retrieve when wish to
let newValue = JSON.parse( window.name );

WebSQL

Share the compatibility with SQL databases with limited storage of 5MB. If you have an older version of the web app and it's hard to functionalize it on a newer version or upgrade it with different versions of the storage mechanism. Then WebSQL is nice to have. However, too low a storage limit, old callback API, and inconsistency of SQL will make it a bit darker, which is fine if it matches your purpose.

We will practice this as follows:

const db = openDatabase('todo', '1.0', 'to-do list', 1024 * 1024);

db.transaction( t => {

  // create table
  t.executeSql('CREATE TABLE task (id unique, name)');

  // add record
  t.executeSql('INSERT INTO task (id,name) VALUES (1, "write article")');

});

// output all items
db.transaction( t => {

  t.executeSql(
    "SELECT * FROM task",
    [],
    (t, res) => { console.log(res.rows); }
  );

});

Enter fullscreen mode Exit fullscreen mode

Now let's understand widely popular web browser or client-side storage APIs:

Here we have two most trending browser-side storage APIs under the experimental stage. We expect them to become browser compatible with managing critical responsibilities. But they may get the green signal for standard practices.

We are talking about the File System Access API and File Directory Entries API.

The browser can read/ write/ update/ delete operations with File System Access API. But you need to enable the permission to that file or directory you want to access on the local file system. Your application will access the behavior of the desktop application through the returned FileSystemHandle. Reduce load at the server side, but we can expect the change in the coming days in this API.

File and Directory Entries API does not require specific permission to access read and writing accessibilities from the domain-specific virtual local file system. If you love adventure, then go with this virtual file system.

Cookies

All cookies store a small amount of data on our activity. It manages the website at the time of login. Cookies data also have an expiry time that can modify or delete the data from the browser and server. A domain has a limit of storing max 20 names. Here the string limit is 4kb.

As you can calculate total limit is 80kb. You can expect 1MB cookie-specific bandwidth by restricting the limit to 50kb and applying requests for ten 1-byte files.

document.cookie = 'cookie1=1';
document.cookie = 'cookie2=tw

Enter fullscreen mode Exit fullscreen mode

To manage the error or any disturbance, it is required to add encodeURIComponent().

document.cookie = `cookie3=${ encodeURIComponent('Hello world!') }`;
Enter fullscreen mode Exit fullscreen mode

DOM Storage

Assign the value to key-value pairs or named attributes to any DOM node. It is not supposed as a standard storage mechanism. It is also referred to as web storage. However, it can hold the value from client systems. You can remove the values by toggling off 'enable DOM storage. It is limited to a very small amount of data.

You can manage the attributes with setAttribute() and getAttribute(). Fix the functionality as disabled or enabled.

Moreover, you can manage the classes through classList API best suitable to hold Boolean variables.

Furthermore, you can do this by adding dataset property adding on the prefix data.

DOM Storage is best suitable to assign or pass client-side and server-side data and values. It is quick to operate while eliminating the DOM node searches and layout modification triggers. However, it s not feasible for permanent data storage. Subsequently, there are chances of overwriting attribute values by the attempt of third-party scripts. Adding on to this, it also asks for the action of serialization and deserialization.

// locate a DOM node
const element = document.getElementById('mycomponent');

// store values
element.myValue1 = 1;
element.setAttribute('myValue2', 2);
element.dataset.myValue3 = 3;

// retreive values
console.log( element.myValue1 ); // 1
console.log( element.getAttribute('myValue2') ); // "2"
console.log( element.dataset.myValue3 ); // "3"
Enter fullscreen mode Exit fullscreen mode

Cache API

It can hold the data of HTTP objects: request and response. It lets you manage the cache resources for a temporary time without requiring internet accessibility. Different browsers have enabled different limits for data storage. On Safari, it's 50MB with a duration of 14 days. On Chrome, it's 100MB. Upgrade the web performance by managing the cache storage in offline mode. It is a promised cache API. you can open the cache and retrieve the info.

// open a cache
const cache = await caches.open( 'myCache' );

// fetch and store response
await cache.add( '/myfile.json' );

const

  // open cache
  cache = await caches.open( 'myCache' ),

  // fetch stored response
  resp = await cache.match( '/myfile.json' ),

  // get content as text
  response = await resp.text();

Enter fullscreen mode Exit fullscreen mode

localstorage and sessionstorage

Both web storage APIs enable setting up the string with name-value pairs. These are easy and supportive with the methods: .getItem(), .setItem(), and removeItem(). One is used for persistent data, and the other is sessionstorage for temporary only till the session is active. These APIs slower the JS operations keeping things synchronous with the domain limit of 5MB.

localStorage.setItem('value1', 1);
localStorage.getItem('value1'); // "1"
localStorage.removeItem('value1'); // gone

Item iteration enabled here: .length, .clear(), .key(N).
Enter fullscreen mode Exit fullscreen mode

You can notice the storage event occurrence across all browser/ windows tabs with modified application views.

window.addEventListener('storage', e => {

  console.log(`key changed: ${ e.key }`);
  console.log(`from       : ${ e.oldValue }`);
  console.log(`to         : ${ e.newValue }`);

})

Enter fullscreen mode Exit fullscreen mode

Avoid using large data/ information; only strings are allowed with the need for serialization and deserialization. Here is the risk of overwriting another component name or unstructured data. Further, if you will try to store large datasets, it will diminish the web performance.

Variables

It does not require any JSON string conversion or serialization and deserialization execution. It manages the data storage quickly to variables without having any storage limit. In case of storage space is used, browser performance and speed will be affected. Variable has volatile behavior thus, performing refresh and navigation will erase data from the browser.\

Const
  a = 1,
  b = 'two',
  c = {
    one: 'Object',
    two: 'three'
  };

Enter fullscreen mode Exit fullscreen mode

It is accessible to overwrite global values through third-party scripts.

IndexedDB

It's similar to the NoSQL database, has a 1GB storage limit, and can approach 60% of total disk space. It enables IE 10+ browser support, transactions, indexes, and search with the integration of asynchronous API; it does not require serialization or deserialization to store javascript value. More on that, IndexedDB allows memory space for massive state data.

However, old API and callback juggling keep it in the back seat of modern-age operations. But it enables wrapper functions. While setting up the database, it requires a name and version number. In case the version is upgraded, then it requires an upgrade function. For great performance and massive data storage, space developers prefer this.

Manage the DB connectivity as follows:

// connect to IndexedDB database
function dbConnect(dbName, version, upgrade) {

  return new Promise((resolve, reject) => {

    const request = indexedDB.open(dbName, version);

    request.onsuccess = e => {
      resolve(e.target.result);
    };

    request.onerror = e => {
      console.error(`connect error: ${ e.target.errorCode }`);
    };

    request.onupgradeneeded = upgrade;

  });

}

Enter fullscreen mode Exit fullscreen mode

Below learn how to initialize the object and connectivity.

(async () => {

  const db = await dbConnect('db', 1.0, e => {

    db = e.target.result;
    db.createObjectStore('mystore');

  })

})();

Enter fullscreen mode Exit fullscreen mode

See how to manage the item transaction with a DB connection.

db.transaction(['mystore'], 'readwrite')
  .objectStore('mystore')
  .add('the value', 'key1')
  .onsuccess = () => console.log( 'added' );

Enter fullscreen mode Exit fullscreen mode

See how to retrieve values:

db.transaction(['mystore'], 'readonly')
  .objectStore('mystore')
  .get('key1')
  .onsuccess = data => console.log( data.target.result );

Enter fullscreen mode Exit fullscreen mode

Wrapping Up

After considering all of the options from the list, we are wrapping this up. Each API serves a different purpose and has a different implementation. For the session, the cookie is nice. For the web component state, you know DOM will work. For UI options, accessibility web storage is the suitable one. If having data dumps in massive amounts, then we have Indexed DB. furthermore, you already know, so practice it accordingly.

Top comments (0)