HTML5 Local Storage Revisited

Local storage is part of the HTML5 Web Storage API and it allows you to store data in the browser. Unlike cookies, data stored using local storage isn’t sent back to the server. All data stays on the client, and you can currently store from 2MB to 10MB. This limit is tied to the specific browser, protocol (HTTP or HTTPS), port, and top level domain in use.

In this article, we’ll discuss how to use this API to improve the performance of a website. I’ll assume that you know what local storage is and the methods exposed, but if you need a refresher I suggest you read the article An Overview of the Web Storage API by Colin Ihrig.

Available disk space

Before we start the discussion of local storage, I want to give you an overview of the available disk space in major mobile and desktop browsers. The following tables are based on the article “Working with quota on mobile browsers”.

Mobile browsers:

Browser Chrome Android Browser Firefox iOS Safari
Version 40 4.3 34 6-8
Space available 10MB 2MB 10MB 5MB

Desktop browsers:

Browser Chrome Opera Firefox Safari Internet Explorer
Version 40 27 34 6-8 9-11
Space available 10MB 10MB 10MB 5MB 10MB

Native cache vs local storage

--ADVERTISEMENT--

When using local storage, your data will stay on the client and persist across sessions and device restarts. As I mentioned in the introduction, the limit of the local storage API is tied to the specific browser (as shown in the previous tables), protocol, port, and top level domain in use. By contrast, the space available on the browser’s native cache is shared across websites, and it’s much smaller on mobile devices. It gets flushed frequently, sometimes even within the same visit. Mobile devices have an additional issue: they’re less powerful than desktop devices, so achieving good performance is a must.

There has been a lot of discussion about local storage performance. For example, Christian Heilmann, formerly with Mozilla, wrote “There is no simple solution for local storage”. Local storage can have a performance hit if not used carefully. The first thing you need to take into account is that it’s a synchronous API, therefore it blocks the main UI thread. Local storage writes and reads data from the hard drive, which can be a much more expensive operation than reading from memory. In order to give you access to the data, local storage needs to read the data from the disk, and that’s where the performance hit occurs. This performance hit is not a major issue with small amounts of data, but it can be noticeable using the full storage limit.

As a good practice you should try to perform as few reads as possible. Also, because we are dealing with a synchronous API, you should try to read data from local storage only after the window.onload event has fired, to avoid blocking the UI thread.

Things have changed

But things are getting better. An article published by Peter McLachlan of Mobify explained that local storage can be 5x faster than native cache on mobile devices.

Smartphone local storage outperforms browser cache

In the appendix of the same article you can see the evolution of the performance of local storage on mobile browsers and how much it’s improved. You can also see that local storage has always been faster than native cache.

Who’s using local storage?

There are some recent cases of websites using local storage to cache assets, such as The Guardian who are using local storage for critical path CSS. You can view this presentation given at Velocity conference 2014 to understand more about how they are able to do this.

Also Smashing Magazine recently started caching web fonts in local storage. In this article about some performance improvements implemented recently on their website, they report deferring web fonts and caching them in local storage among the changes that led to the most effective improvements.

A note on Private Browsing

As reported on caniuse.com, under the tab known issues, when running in private or incognito mode, Safari, iOS Safari, and Android browsers don’t support setting items in local storage.

Other browsers such as Chrome and Firefox allow you to store data in local storage under private mode, but the data is purged when you exit private mode. This is due to privacy issues, as someone might use the persistent data to learn about the user’s actions when in private mode.

This issue may break your application’s behavior if a value set under a previous session is expected to be there at a subsequent visit. So, in order to use local storage safely, it’s a good practice not only to test for support, but also to test for the capacity to get and set items.

For more info on local storage behavior under private mode and on how to check local storage content in different browsers, you can use the article “Don’t Forget To Check Private Browsing Mode When Testing” as a reference.

Conclusion

Maybe it’s time that we start revisiting local storage and its potential usage, especially on mobile devices where we can use it to avoid latency bottlenecks. We can start thinking about new ways to cache our assets, and then serve them instantly to our users. We’ve seen there are already some successful implementations of local storage usage in unconventional ways.

Replies

  1. Local Storage is a neat concept but since it is a String:String key:value pair store you'll need to deal with conversions when dealing with numbers, dates, maps, arrays, etc.

    The 5MB Safari limit also makes large scale apps just simply not an option. However the simplicity of the API is appreciated and thus Mozilla's localForage framework http://mozilla.github.io/localForage/ is a great alternative with a very similar (but async) API that sits on top of the more capable IndexedDB APIs.

    Hopefully in time all browsers will support the Quota API and or increase the localStorage to a realistic level! wink

  2. The good news for this particular issue, is that JSON is an excellent format in which to store such data.

  3. Local storage is also a handy way of transferring data between windows or tabs, if that's needed.

    You can test the storage limit and user settings with exception handling. If referring to window.localStorage throws an error, then user security policy has disabled it. If setting a value throws an error, then you've exceeded the data limit. The safest approach is to use exception handling every time you use local storage.

    try
    {
        var storage = window.localStorage;
    }
    catch(ex)
    {
        //storage is disabled by user settings
    }
    
    
    try
    {
        storage.key = value;
    }
    catch(ex)
    {
        //set would exceed storage quota
    }

    JSON is very useful, but JSON itself is expensive to parse -- if the data is complex and hierarchical, then yeah, JSON is a good choice. But if it's just a bunch of simple values, then it's better to use a simple delimiter (like comma) and parse that manually.

    But in that browser cache vs local storage graph, are the colour codes the wrong way round, or am I missing something? The written conclusion is that local storage is faster, but the graph shows that browser cache is faster in every case.

  4. That's kind of my point though -- storage and cookies have different features. So what possible use is a function that falls back to cookies if storage isn't available?

  5. That's the bottom line isn't it -- obfuscation isn't security. It doesn't matter how difficult it is or how determined or knowledgeable someone would have to be; if the data is exposed, then it's not secure.

    Even if you encrypted it, well then you'd have to decrypt it again -- using client-side code ... which the user can see, and use themselves!

    Local storage is useful for a whole host of things, but secure information is not one of those things smile

14 more replies