This is a review of the 5th course in the HTML5 learning path on Pluralsight. This follows on from courses such as HTML5 Fundamentals and HTML5 Advanced Topics.
Whereas earlier courses took a quick look across a wide range of APIs, this is much more of a deep dive look at some of the most important APIs in HTML5: the persistence APIs.
This is the longest course in the learning path at 5 hours 29 minutes.
It feels like three courses in one, and if you are only interested in learning one of the three technologies (Web Storage/IndexedDB/File System), you can absolutely do this by just watching the modules associated with the particular technology you want to learn.
Having said that, until you know at least a bit about each technology, you won’t know be able to judge which technology is best suited to your needs.
I can quickly give you some very simple and basic guidance on this: if you have simple needs, use Web Storage. If you have more advanced needs, use Indexed DB. Only consider using the File System API if you don’t need to support browsers such as Microsoft Edge, Firefox and Safari.
Craig begins with the relative browser support of various HTML5 APIs. These are no longer very accurate: all are better supported today (but see my review of HTML5 Advanced Topics before you use the Application Cache).
Check out the latest on Can I Use:
I had not come across mockJSON before, but it is incredibly powerful. As Craig explains, data generation features include
You can try it for yourself on Menno van Slooten’s site.
In the course Craig mentions some differences between Web Storage and IndexedDB, but doesn’t give a good explanation on when you should use one over the other. For understanding this, I have found this programmer stackexchange thread very helpful.
Web Storage is very well supported now, but Craig points out some resources for providing fallback support.
The caveats clip is interesting, explaining how local storage works in private mode.
There are three different ways of getting and setting local storage values: using the dot operator, get/set functions, and using the bracket notation, all of which are demonstrated in the same clip. Craig likes using the dot operator, but use whichever you prefer.
There are also a couple of ways of removing data from local storage: you can either remove items on an individual basis or call clear to remove everything in one go.
For a real world example we see an input form that automatically saves the entered data to local storage.
Craig runs through a localDataService module that he wrote, which provides a nice abstraction away from some of the implementation details and makes it easier to switch to IndexDB or another storage mechanism if you wish. Also shown is how to use it inside a view model.
The full specification is available at w3.org/TR/IndexedDB/
Also see the Mozilla Developer Network.
IndexedDB is an Object-Oriented Database stored on the client.
The Event Lifecycle begins with an Open Request, which passes the version number of the database that you want to open.
If it is a new version, the onupgradeneeded event fires, allowing you to create and remove object stores and indexes. If it is the current version, this step is skipped.
Once this work is complete, onsuccess fires, giving you the reference to the open database.
The onerror event is fired if there is an error at any point.
There are two APIs that you can use to work with IndexedDB. There’s an asynchronous API (which is like using AJAX requests), and then there is the Synchronous Web Workers API, which is covered in Craig’s Advanced Topics course.
On can I use, you can see that Safari does not support Indexed DB, however note the warning about buggy behavior. Mobile browser support is also pretty good now, however you’ll still want to listen to what Craig says about fallbacks and polyfills.
You can find the midnight dog walker’s shim at https://github.com/axemclion/IndexedDBShim
Craig makes the point that when you include Web SQL support, every modern browser now supports databases on the client.
Craig warns that the API is complex, and later covers one approach to simplify your work.
The biggest disadvantage is that it is browser-specific, so if the user spends time on your site, and then comes back later using a different browser, there’s no way to access the data that you previously stored on their browser.
IndexDB: Initialization and CRUD
IndexDB: Cursors, Indexes and Ranges
Covers performing searches, filtering and sorting results.
Craig uses mockJSON to create 100 people objects, which are inserted into the database.
When a cursor runs, the success event fire for each object extracted from the database. There is a continue function on the cursor, which does just that.
Indexes retrieve only one object from the database (they match against the first value they find(
For doing a Select Where type of query, use Ranges. One type of Range is a bound, which is used for setting a maximum or minimum value.
There are open and closed bounds. open bounds mean the specified value is excluded from the result set
closed bounds include the specified value in the result set.
You can also do bound(10, 20) which specifies both the lower and upper bounds.
Bounds are closed by default, but you can specify that bounds are open like this:
bound(10, 20, true, true)
Finally if you are only interested in results matching one particular value, use the “only” bound:
These keywords can also be used for string queries, e.g.
var range1 = IDBKeyRange.only(lastName);
var range2 = IDBKeyRange.lowerBound(lastName);
var range3 = IDBKeyRange.upperBound(lastName);
Craig shows how to pass a range into a cursor, make a cursor request, and log the extracted results on success.
You can also change the direction of the cursor, e.g.
var cursorRequest = index.openCursor(range, ‘prev’);
‘next’, ‘nextUnique’ and ‘prevUnique’ are also explained in this module.
Also see the the cursor concept section of the IndexedDB specification.
IndexDB: Keys, Capacity, Performance and Versions
This module covers strategies for uniquely identifying data, and looks at the browser performance when large amounts of data is stored. It also covers versioning.
Craig explains the autoIncrement key (similar to identity insert in SQL, but not part of the data), and the keyPath. You can use both autoIncrement and keyPath together if you wish, and the first demo shows how to do this, as well as how to use a GUID (or UUID).
Also see the options object concept in the IndexedDB specification
There are some situations where you will want to have one set of keys to uniquely identify objects on the client (auto incremented value, or GUID), and another set of keys to uniquely identify the objects on the server. You can then append the server key values to the objects on the client.
Working with Large Sets of Data
There is a demo with 500,000 objects in a table. The query results are pretty quick: 2 or 3 seconds to retrieve 15 to 30 thousand rows.
Managing Database Versions
In the versions clip, we see 3 different versions of the database with logic for checking the schema is correct.
Make sure the current instance of the database is closed before changing the version and opening a new instance.
Once you upgrade to a newer version of the database, you cannot access the earlier version.
This demo requests 58MB through AJAX and then attempts to insert it into the database. This just works in Chrome but in some browsers the user will need to give permission to go over a 50MB quota.
IndexDB: Abstractions & Implementing and Edit Screen
In this module we finally get to see a real world type of demo: a form to add homes into a database.
Included in this module is error handling, deleting and opening a database, CRUD, and the view model code.
For creating the UUID (or GUID) see this stack overflow Q&A.
File System: Introduction, Concepts & Initialization
We learn that the same policies on storage quotas generally apply to all of these persistence technologies. For example you can go above 50MB in Chrome for both the File System as well as for IndexedDB.
Advice on Browser Support is still generally, and unfortunately, true, with only Chrome and Opera supporting the File System. There is good support for File API but the File System API specification is effectively dead.
See can I use for details on File System support. This picture is unlikely to change much in the future.
In the list of File API fallbacks & polyfills, Craig highlights Eric Biedelman’s IDB Filesystem, which is based on Indexed DB.
Since this course was recorded, Eric has also written a popular wrapper for this API called filer, which uses Unix commands such as cp, mv and ls.
In the caveats clip, Craig warns that the File API is non transactional and callback heavy, with no search support, and with case sensitive file names. It will not work across different browsers, so your users will need to remember to return to your web application using the same browser (Chrome or Opera) as they previously used.
We also see that the user must give permission for the files to be written to their disk drive.
You can download the Chrome plugin HTML5 Filesystem Explorer (formerly known as peephole) and explore temporary and persistent memory
File System: Directories – Create, List, Delete, Move & Copy
This is a set of demonstrations showing the low level code for creating directories and sub directories, and reading them. This module also covers deletion including recursive deletion of directories and files, moving copying and renaming.
File System: Building an Abstraction Layer over Directories
This module wraps up the complexity in an abstraction layer. By the end of this module, the code that you use is much simpler and more expressive.
File System: Files – Create, Read, Write, Delete, Move & Copy
This module begins with an explanation for how to work with the files at a low level, and then builds an abstraction layer for making this work more manageable.
File System: Testing Capacity Limits & Implementing a File Editor
This module first shows that you can write out 58MB files in Chrome. It then demonstrates a file editor in the browser. Again this example uses jQuery, Knockout and Bootstrap.
This covers three libraries:
store js is a local storage library written by Marcus Westin that provides fallback support for old browsers.
Internet Explorer 5 to 7 has a user data API. And Firefox 2+ uses Global Storage. And of course all browsers have the ability to store data in memory, which is the ultimate fallback
amplify js is another web storage library, with some features in addition to what store.js provides, such as time based expiration, an extensibility model, and abstracting AJAX requests and interfaces into UI components.
Also see Shawn Wildermuth’s introduction to Amplify in the enabling saving and wrap-up clip at the end of his Play by Play course.
lawnchair js is a JSON storage library, and is based on working with adapters, the default one being the DOM adapter which writes to local Storage. Alternative adapters include:
gears-sqlite (for old android browsers)
3 thoughts on “HTML5 Web Storage, IndexedDB and File System”
Pingback: HTML5 Learning Path | Zombie Code Kill
Pingback: Building Mobile Apps with the Ionic Framework and Angular JS | Zombie Code Kill
Pingback: Polymer and Progressive Web Apps – Google I/O 2016 | Zombie Code Kill