Tutorial

Built-in Web Modules: How to Use KV Storage

Published on March 22, 2019
Built-in Web Modules: How to Use KV Storage

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

The release of KV Storage is a big deal for the web platform. It’s part of the Standard Library Proposal which could see a more extensive standard library being introduced for JavaScript.

Before jumping in to what kv-storage is, let’s first discuss how we can store data within the browser. If I wanted to store some local data right now, one of my main options would be the use of localStorage.

With that in mind, let’s create a simple Todo application with JavaScript that takes advantage of localStorage. We’ll need two files - index.html and main.js:

main.js
const TODOS_KEY = 'todos';
const ul = document.getElementsByTagName('ul')[0];

const showExistingTodos = todos => {
  if (todos.length > 0) {
    todos.map(todo => {
      addLi(todo);
    });
  }
};

const addTodo = () => {
  const input = document.getElementById('todoInput').value;

  if (input.length > 0) {
    addLi(input);
    saveTodo(input);

    document.getElementById('todoInput').value = '';
  }
};

const addLi = text => {
  const li = document.createElement('li');

  li.appendChild(document.createTextNode(text));

  ul.appendChild(li);
};

const saveTodo = todo => {
  let loadedTodos = loadTodos();

  loadedTodos = [...loadedTodos, todo];

  localStorage.setItem(TODOS_KEY, JSON.stringify(loadedTodos));
};

const loadTodos = () => {
  const todos = JSON.parse(localStorage.getItem(TODOS_KEY));

  return todos != null ? todos : [];
};

const clearTodos = () => {
  localStorage.removeItem(TODOS_KEY);

  const todos = Array.from(document.getElementsByTagName('li'));

  todos.map(todo => ul.removeChild(todo));
};

const todos = loadTodos();

showExistingTodos(todos);
index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div>
    <input id="todoInput" type="text" />  
    <button onclick="addTodo()">Add Todo</button>
    <button onclick="clearTodos()">Clear todos</button>
  </div>

  <ul>

  </ul>

  <script src="main.js"></script>
</body>
</html>

While this could definitely be improved, we now have an application that we can use as an example. If we try and add some Todo items and then refresh the page, we’ll see that they appear instantly!

Hmm… I did some research and found out that localStorage is synchronous. What does that mean for our application?

Essentially, this means that calls to localStorage will block rendering inside of the DOM. This may may represent a problem if we had lots of elements in localStorage and will significantly impact performance.

Let’s take a look at an experimental built-in module named KV storage (for key/value storage). This is built on IndexedDB, an asynchronous storage API.

Why not use IndexedDB natively then?

The use of KV storage gives us a more intuitive API that is similar to localStorage. We also don’t need to turn to a third party IndexedDB library, we can now use this directly from within the browser!

KV Storage

For this example we’ll need to enable Experimental Features within Chrome. Inside of your Chrome browser, navigate to the following address:

Select “Enabled” on Experimental Web Platform features: chrome://flags/#enable-experimental-web-platform-features.

It’s also a good idea to use Chrome Canary for any and all experimental/new Web features. I’ll be using it for our example.

We’ll now need to perform the following updates:

Inside of index.html, import main.js as a module:

<script type="module" src="main.js"></script>

Next, we can update our saveTodo function to use storage.set() instead of localStorage.setItem()

const saveTodo = async todo => {
  let loadedTodos = await loadTodos();

  loadedTodos = [...loadedTodos, todo];

  await storage.set(TODOS_KEY, loadedTodos);
};

Our loadTodos function uses storage.get() instead of localStorage.getItem():

const loadTodos = async () => {
  const todos = await storage.get(TODOS_KEY);

  return todos != null ? todos : [];
};

Notice here how we’re dealing with the asynchronicity with ease using async/await functions.


Finally, we can improve our clearTodos function by using storage.delete() instead of localStorage.removeItem():

const clearTodos = () => {
  storage.delete(TODOS_KEY);

  const todos = Array.from(document.getElementsByTagName('li'));

  todos.map(todo => ul.removeChild(todo));
};

We’ll also need to expose these to the window object:

window.addTodo = addTodo;
window.clearTodos = clearTodos;

Our application now works once again, but instead of localStorage it uses the std:kv-storage built-in Web module. The best thing about this? It uses IndexedDB under the hood!

This means everything is asynchronous (as referenced by our async and await promise calls, too).

Client support

What if the browser doesn’t support kv-storage? At the moment, this is extremely likely. Luckily, there’s a polyfill available here: https://github.com/GoogleChromeLabs/kv-storage-polyfill.

I’d recommend you add this to your application if you plan on using kv-storage in production at this stage.

Further reading

Google has prepared a demo on kv-storage that you may find interesting to read. Here’s the URL: https://rollup-built-in-modules.glitch.me/

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel