Continuing from a previous post, moving from Local Storage to IndexedDB, I set about a journey to fully embrace IndexedDB. Not wanting to reinvent the wheel, by enabling promises/async in calls to indexedDB, I’ve decided to use a 3rd party wrapper.
I started by looking at the top libraries focusing on popularity, if they had a fallback, if they could be used on on the server side (node), if they supported sync with a SS database, and how easy it would be to import/export the raw data.
Library | Stars/ used by | IndexedDB | localStorage (fallback) | NodeJS | Sync | Export / Import |
Dexie.js | 7k/8k | Yes | No, not really. | /= can polyfill | /=adapter required | Yes (adapter) |
PouchDB | 14k/ | Yes | Yes (adapter) | Yes (adapter) | Yes! | / = maybe with some other libs |
RxDB | 17k/744 | Yes | No | Yes | Yes | Yes |
localForage | 19k/176k | Yes | Yes | No | No | No |
lowdb | 16k/138k | No | Yes | Yes | No | kind of, JSON |
idb-keyval | 2k/34k | Yes | No | No | No | No |
idb | 4k/168k | Yes | No | No | No | No |
This was a high level evaluation, you can see my more detailed notes in this Google Spreadsheet
In my particular case, I was looking for a replacement for LocalStorage, so I need it to use IndexDB. I don’t care about a fallback due to all major browsers now supporting indexedDB, I would only be using it on the client side, and I didn’t care about export/import capabilities.
Being able to sync would have been nice, but my serverside db is MongoDB, which isn’t an option with any of the wrappers. I did have a few conversations with Nolan of PouchDB and to be honest, if I wasn’t already married to MongoDB and have my own sync algorithm, I’d give it a more serious consideration.
Here’s a graph from npm trends regarding the popularity for the top packages.
Based on my needs, popularity, and how recently the libraries were updated. I narrowed it down to localForage, IDB, and IDB-Keyval.
LocalForage is the oldest and hence has support for older browsers, and so has support for all 3 types of client storage, (localstorage, websql, and indexeddb). After reviewing the API, I decided to pass on it, as even now, much of their docs mention fallback capabilities; like serializing json to strings for LocalStorage if necessary. Although it’s very popular, and used by 176k other projects, I decided to focus on IDB and the Keyval version, both written by Jake Archibald of Google.
IDB came first in 2017, then IDB-Keyval a year later. Why would he make two libraries basically doing the same thing? After reviewing the docs and APIs, it looks like the first version was a promised based api around all the typical indexedDB functions. It’s basically indexedDB with “ennhancements.” As Jake says, it’s “library that mostly mirrors the IndexedDB API, but with small improvements that make a big difference to usability.” If you are familiar with using indexedDB manually, the IDB package will feel the same. It does add things like returning promises rather than using IDBRequest event triggers.
IDB-Keyval on the other hand, follows more closely with the LocalStorage API. LocalStorage’s ease of use was a key reason for its popularity over the more complex indexedDB. Besides adding promises, IDB didn’t address that complexity, so maybe that’s why Jake later created IDB-Keyval.
If your use of a local store happens to be limited to key-value storage, it seems like it might be the better version including extra methods like update (rather then get/set), and setMany (rather than using a Promise.All) which aren’t in IDB. They both however share the basics like get/set/delete/clear/keys. In the keyvalue examples of IDB, Jake mentioned, “This is very similar to localStorage
, but async. If this is all you need, you may be interested in idb-keyval. You can always upgrade to this library later.”
So, that’s what I’m going to do. Start with IDB-Keyval and upgrade IF necessary, rather than using half of a library and possibly having to keep up with newer versions which update code I might never use, not to mention possible future API changes.
My advise is if your use-case calls for full client database functionality like: custom queries, ordering, using cursors with ranges and direction, sorting, etc, go with IDB. If, on the other hand, you simply need LocalStorage functionality, use IDB-Keyval. Both are readily updated and, in my view, represent the best two options for indexedDB wrappers.
BTW, if necessary, I will update this article as I’ll be implementing the aforementioned library in my own application in the coming days. If you don’t see an update, that means things went well and i’m happy with my decision.