HTML5 Tutorial
- Offline Storage - 2020
Persistent local storage is one of the areas where native client applications have held an advantage over web applications.
For native applications, the operating system typically provides an abstraction layer for storing and retrieving application-specific data like preferences or runtime state. These values may be stored in the registry, INI files, XML files, or some other place according to platform convention. If our native client application needs local storage beyond key/value pairs, we can embed our own database, invent our own file format, or any number of other solutions.
Historically, web applications have had none of these luxuries. Cookies were invented early in the web's history, and indeed they can be used for persistent local storage of small amounts of data. But they have several potentially deal breaking downsides:
- Cookies are included with every HTTP request, thereby slowing down your web application by needlessly transmitting the same data over and over .
- Cookies are included with every HTTP request, which is not only a waste of resources, but also by sending data unencrypted over the internet (unless your entire web application is served over SSL) it has security issues.
- Browsers are not required to keep more than 20 cookies per Web server.
- Cookies are limited to about 4 Kb of data ((including both name and value) - enough to slow down your application, but not enough to be terribly useful.
What we really want is persistent local storage that never leaves the client browser. There have been a number of attempts to achieve this, each ultimately unsatisfactory in different ways.
HTML5 Storage (Local Storage, DOM Storage, or Offline Storage) is set to provide a standardized API, implemented natively and consistently in multiple browsers, without having to rely on third-party plugins.
So what is HTML5 Storage? Simply put, it's a way for web pages to store named key/value pairs locally, within the client web browser. Like cookies, this data persists even after you navigate away from the web site, close your browser tab, exit your browser, or what have you. Unlike cookies, this data is never transmitted to the remote web server. Unlike all previous attempts at providing persistent local storage, it is implemented natively in web browsers, so it is available even when third-party browser plugins are not.
From our JavaScript code, we'll access HTML5 Storage through the localStorage object on the global window object. Before we can use it, we should detect whether our browser supports it:
function supports_html5_storage() { return ('localStorage' in window) && window['localStorage'] !== null; }
But instead of writing this function yourself, you can use Modernizr to detect support for HTML5 Storage:
if (Modernizr.localstorage) { // window.localStorage is available! } else { // no native support for HTML5 storage : // maybe try dojox.storage or a third-party solution }
HTML5 Storage is based on named key/value pairs. We store data based on a named key, then we can retrieve that data with the same key. The named key is a string. The data can be any type supported by JavaScript, including strings, booleans, integers, or floats. However, the data is actually stored as a string. If we are storing and retrieving anything other than strings, we will need to use functions like parseInt() or parseFloat() to coerce your retrieved data into the expected JavaScript datatype.
interface Storage { getter any getItem(in DOMString key); setter creator void setItem(in DOMString key, in any data); };
Calling setItem() with a named key that already exists will silently overwrite the previous value. Calling getItem() with a non-existent key will return null rather than throw an exception.
There are also methods for removing the value for a given named key, and clearing the entire storage area (that is, deleting all the keys and values at once).
interface Storage { deleter void removeItem(in DOMString key); void clear(); };
Calling removeItem() with a non-existent key will do nothing. Finally, there is a property to get the total number of values in the storage area, and to iterate through all of the keys by index (to get the name of each key).
interface Storage { readonly attribute unsigned long length; getter DOMString key(in unsigned long index); };
If we call key() with an index that is not between 0, length-1, the function will return null.
If we want to keep track programmatically of when the storage area changes, we can trap the storage event. The storage event is fired on the window object whenever setItem(), removeItem(), or clear() is called and actually changes something. For example, if we set an item to its existing value or call clear() when there are no named keys, the storage event will not fire, because nothing actually changed in the storage area.
The storage event is supported everywhere the localStorage object is supported, which includes Internet Explorer 8. IE 8 does not support the W3C standard addEventListener (although that will finally be added in IE 9). Therefore, to hook the storage event, we'll need to check which event mechanism the browser supports.
if (window.addEventListener) { window.addEventListener("storage", handle_storage, false); } else { window.attachEvent("onstorage", handle_storage); };
The handle_storage callback function will be called with a StorageEvent object, except in Internet Explorer where the event object is stored in window.event.
function handle_storage(e) { if (!e) { e = window.event; } }
Let's talk about the limitations of the HTML5 Storage.
"5 megabytes" is how much storage space you get by default. This is surprisingly consistent across browsers, although it phrased as no more than a suggestion in the HTML5 Storage specification. One thing to keep in mind is that we're storing strings, not data in its original format. If we're storing a lot of integers or floats, the difference in representation can really add up. Each digit in that float is being stored as a character, not in the usual representation of a floating point number. QUOTA_EXCEEDED_ERR is the exception that will get thrown if we exceed our storage quota of 5 megabytes. "No" is the answer to the next obvious question, "Can I ask the user for more storage space?" No browser supports any mechanism for web developers to request more storage space.
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization