Top Related Projects
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.
Simple and fast JSON database
:kangaroo: - PouchDB is a pocket-sized database.
A fast, local first, reactive Database for JavaScript Applications https://rxdb.info/
:nut_and_bolt: A relentless key-value store for the browser.
The fastest and simplest library for SQLite3 in Node.js.
Quick Overview
Dexie.js is a minimalistic wrapper for IndexedDB, providing a clean and simple API for working with client-side databases in web applications. It offers a powerful yet easy-to-use interface for storing and retrieving JavaScript objects, making it an excellent choice for offline-capable web apps.
Pros
- Simple and intuitive API, reducing the complexity of working with IndexedDB
- Supports complex querying and indexing capabilities
- Offers robust error handling and transaction management
- Lightweight and fast, with minimal overhead
Cons
- Limited browser support for older versions (IE10 and below)
- May require additional setup for optimal performance in large-scale applications
- Learning curve for developers unfamiliar with IndexedDB concepts
- Some advanced IndexedDB features may not be directly exposed
Code Examples
- Creating a database and defining object stores:
const db = new Dexie('MyDatabase');
db.version(1).stores({
friends: '++id, name, age',
pets: '++id, name, species'
});
- Adding items to the database:
await db.friends.add({ name: 'John', age: 30 });
await db.pets.add({ name: 'Fluffy', species: 'cat' });
- Querying the database:
const youngFriends = await db.friends.where('age').below(25).toArray();
const cats = await db.pets.where('species').equals('cat').toArray();
- Updating records:
await db.friends.update(1, { age: 31 });
await db.pets.where('species').equals('dog').modify({ species: 'canine' });
Getting Started
- Install Dexie.js:
npm install dexie
- Import and use Dexie in your project:
import Dexie from 'dexie';
const db = new Dexie('MyDatabase');
db.version(1).stores({
items: '++id, name, category'
});
// Open the database
db.open()
.then(() => console.log('Database opened successfully'))
.catch(err => console.error('Error opening database:', err));
// Use the database
async function addItem(name, category) {
try {
const id = await db.items.add({ name, category });
console.log(`Item added with id ${id}`);
} catch (error) {
console.error('Error adding item:', error);
}
}
addItem('Example Item', 'Test Category');
This quick start guide demonstrates how to create a database, define an object store, open the database, and perform a basic operation (adding an item).
Competitor Comparisons
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.
Pros of localForage
- Simple API with a key-value store interface, making it easy to use for developers familiar with localStorage
- Automatic selection of the best available storage mechanism (IndexedDB, WebSQL, or localStorage)
- Built-in support for multiple storage drivers and easy driver customization
Cons of localForage
- Limited querying capabilities compared to Dexie.js
- Lack of advanced features like indexing and complex data structures
- May have slightly lower performance for large datasets or complex operations
Code Comparison
localForage:
localforage.setItem('key', 'value').then(function() {
return localforage.getItem('key');
}).then(function(value) {
console.log(value);
}).catch(function(err) {
console.log(err);
});
Dexie.js:
db.friends.add({name: 'John', age: 30}).then(function() {
return db.friends.where('age').above(25).toArray();
}).then(function(friends) {
console.log(friends);
}).catch(function(error) {
console.error(error);
});
Summary
localForage offers a simpler API and automatic storage mechanism selection, making it ideal for basic storage needs. However, Dexie.js provides more advanced features and better performance for complex data operations, making it suitable for larger applications with sophisticated data management requirements.
Simple and fast JSON database
Pros of lowdb
- Simpler API and easier to set up for small projects
- Supports JSON file-based storage out of the box
- Lightweight with minimal dependencies
Cons of lowdb
- Limited scalability for large datasets
- Lacks advanced querying capabilities
- No built-in support for complex data types or indexing
Code Comparison
lowdb:
const low = require('lowdb')
const FileSync = require('lowdb/adapters/FileSync')
const adapter = new FileSync('db.json')
const db = low(adapter)
db.defaults({ posts: [] }).write()
db.get('posts').push({ id: 1, title: 'lowdb is easy' }).write()
Dexie.js:
const db = new Dexie('MyDatabase')
db.version(1).stores({
posts: '++id, title'
})
db.posts.add({ title: 'Dexie is powerful' })
.then(() => db.posts.where('title').equals('Dexie is powerful').toArray())
.then(posts => console.log(posts))
Summary
lowdb is ideal for small projects requiring simple JSON storage, while Dexie.js offers more robust features for larger applications needing advanced querying and indexing capabilities. lowdb's simplicity comes at the cost of scalability, whereas Dexie.js provides a more comprehensive solution for complex data management needs.
:kangaroo: - PouchDB is a pocket-sized database.
Pros of PouchDB
- Synchronization capabilities with CouchDB and other PouchDB instances
- Built-in support for offline-first applications
- Extensive ecosystem and plugin support
Cons of PouchDB
- Larger file size and potentially slower performance for simple use cases
- More complex API compared to Dexie.js
- Steeper learning curve, especially for developers new to NoSQL databases
Code Comparison
Dexie.js:
const db = new Dexie('MyDatabase');
db.version(1).stores({
friends: '++id, name, age'
});
await db.friends.add({ name: 'John', age: 30 });
const john = await db.friends.where('name').equals('John').first();
PouchDB:
const db = new PouchDB('MyDatabase');
await db.put({ _id: 'john', name: 'John', age: 30 });
const result = await db.find({
selector: { name: 'John' }
});
const john = result.docs[0];
Both libraries provide easy-to-use APIs for working with IndexedDB, but PouchDB offers more advanced features like synchronization at the cost of increased complexity. Dexie.js focuses on simplicity and performance for basic IndexedDB operations, while PouchDB is better suited for applications requiring offline support and data syncing across multiple devices or servers.
A fast, local first, reactive Database for JavaScript Applications https://rxdb.info/
Pros of RxDB
- Real-time synchronization and conflict resolution
- Built-in support for reactive programming using RxJS
- Advanced querying capabilities, including mango queries
Cons of RxDB
- Steeper learning curve, especially for developers unfamiliar with RxJS
- Larger bundle size due to additional features and dependencies
Code Comparison
RxDB:
const db = await createRxDatabase({
name: 'heroesdb',
adapter: 'idb'
});
const heroesCollection = await db.addCollections({
heroes: {
schema: mySchema
}
});
const subscription = heroesCollection.heroes
.find()
.$.subscribe(heroes => console.log('heroes:', heroes));
Dexie.js:
const db = new Dexie('heroesdb');
db.version(1).stores({
heroes: '++id, name, power'
});
db.heroes.toArray().then(heroes => console.log('heroes:', heroes));
RxDB offers a more reactive approach with real-time updates, while Dexie.js provides a simpler API for basic IndexedDB operations. RxDB's code involves setting up a database, adding collections, and subscribing to changes. Dexie.js focuses on defining a schema and performing queries. The choice between the two depends on the specific needs of your project, with RxDB being more suitable for complex, real-time applications, and Dexie.js for simpler, straightforward IndexedDB usage.
:nut_and_bolt: A relentless key-value store for the browser.
Pros of ImmortalDB
- Simpler API with a focus on key-value storage
- Built-in support for multiple storage backends (LocalStorage, IndexedDB, Cookies)
- Automatic fallback mechanism for better cross-browser compatibility
Cons of ImmortalDB
- Limited querying capabilities compared to Dexie.js
- Lacks advanced features like indexing and complex data structures
- Smaller community and fewer resources available
Code Comparison
ImmortalDB:
import ImmortalDB from 'immortal-db';
await ImmortalDB.set('key', 'value');
const value = await ImmortalDB.get('key');
Dexie.js:
import Dexie from 'dexie';
const db = new Dexie('MyDatabase');
db.version(1).stores({ items: '++id, name, category' });
await db.items.add({ name: 'Item', category: 'Category' });
const items = await db.items.where('category').equals('Category').toArray();
ImmortalDB provides a straightforward key-value storage solution with built-in support for multiple storage backends, making it easier to use for simple storage needs. However, it lacks the advanced querying and indexing capabilities of Dexie.js.
Dexie.js offers a more powerful and flexible solution for complex data storage and retrieval, with support for indexing, advanced querying, and complex data structures. It's better suited for applications requiring sophisticated data management but may have a steeper learning curve compared to ImmortalDB.
The fastest and simplest library for SQLite3 in Node.js.
Pros of better-sqlite3
- Native C++ SQLite3 binding, offering superior performance for Node.js applications
- Synchronous API, simplifying code structure and reducing callback complexity
- Full support for prepared statements, enhancing query efficiency and security
Cons of better-sqlite3
- Limited to Node.js environments, not suitable for browser-based applications
- Requires compilation of native modules, which can complicate deployment
- Steeper learning curve for developers unfamiliar with SQLite syntax
Code Comparison
better-sqlite3:
const db = new Database('foobar.db');
const stmt = db.prepare('INSERT INTO users VALUES (?, ?)');
const info = stmt.run('John Doe', 35);
Dexie.js:
const db = new Dexie('MyDatabase');
db.version(1).stores({ users: '++id, name, age' });
await db.users.add({ name: 'John Doe', age: 35 });
better-sqlite3 provides a more traditional SQL approach, while Dexie.js offers an object-oriented interface for IndexedDB. The choice between them depends on the specific requirements of your project, such as the target environment (Node.js vs. browser) and the preferred database paradigm.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Dexie.js
Dexie.js is a wrapper library for indexedDB - the standard database in the browser. https://dexie.org.
Why Dexie.js?
IndexedDB is the portable database for all browser engines. Dexie.js makes it fun and easy to work with.
But also:
- Dexie.js is widely used by 100,000 of web sites, apps and other projects and supports all browsers, Electron for Desktop apps, Capacitor for iOS / Android apps and of course pure PWAs.
- Dexie.js works around bugs in the IndexedDB implementations, giving a more stable user experience.
- It's an easy step to make it sync.
Hello World
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/dexie/dist/dexie.js"></script>
<script>
//
// Declare Database
//
const db = new Dexie('FriendDatabase');
db.version(1).stores({
friends: '++id, age'
});
//
// Play with it
//
db.friends.add({ name: 'Alice', age: 21 }).then(() => {
return db.friends
.where('age')
.below(30)
.toArray();
}).then(youngFriends => {
alert (`My young friends: ${JSON.stringify(youngFriends)}`);
}).catch (e => {
alert(`Oops: ${e}`);
});
</script>
</head>
</html>
Yes, it's that simple. Read the docs to get into the details.
Hello World (for modern browsers)
All modern browsers support ES modules and top-level awaits. No transipler needed. Here's the previous example in a modern flavour:
<!DOCTYPE html>
<html>
<head>
<script type="module">
// Import Dexie
import { Dexie } from 'https://unpkg.com/dexie/dist/modern/dexie.mjs';
//
// Declare Database
//
const db = new Dexie('FriendDatabase');
db.version(1).stores({
friends: '++id, age'
});
//
// Play with it
//
try {
await db.friends.add({ name: 'Alice', age: 21 });
const youngFriends = await db.friends
.where('age')
.below(30)
.toArray();
alert(`My young friends: ${JSON.stringify(youngFriends)}`);
} catch (e) {
alert(`Oops: ${e}`);
}
</script>
</head>
</html>
Hello World (React + Typescript)
Real-world apps are often built using components in various frameworks. Here's a version of Hello World written for React and Typescript. There are also links below this sample to more tutorials for different frameworks...
import React from 'react';
import { Dexie, type EntityTable } from 'dexie';
import { useLiveQuery } from 'dexie-react-hooks';
// Typing for your entities (hint is to move this to its own module)
export interface Friend {
id: number;
name: string;
age: number;
}
// Database declaration (move this to its own module also)
export const db = new Dexie('FriendDatabase') as Dexie & {
friends: EntityTable<Friend, 'id'>;
};
db.version(1).stores({
friends: '++id, age',
});
// Component:
export function MyDexieReactComponent() {
const youngFriends = useLiveQuery(() =>
db.friends
.where('age')
.below(30)
.toArray()
);
return (
<>
<h3>My young friends</h3>
<ul>
{youngFriends?.map((f) => (
<li key={f.id}>
Name: {f.name}, Age: {f.age}
</li>
))}
</ul>
<button
onClick={() => {
db.friends.add({ name: 'Alice', age: 21 });
}}
>
Add another friend
</button>
</>
);
}
Tutorials for React, Svelte, Vue, Angular and vanilla JS
Performance
Dexie has kick-ass performance. Its bulk methods take advantage of a lesser-known feature in IndexedDB that makes it possible to store stuff without listening to every onsuccess event. This speeds up the performance to a maximum.
Supported operations
above(key): Collection;
aboveOrEqual(key): Collection;
add(item, key?): Promise;
and(filter: (x) => boolean): Collection;
anyOf(keys[]): Collection;
anyOfIgnoreCase(keys: string[]): Collection;
below(key): Collection;
belowOrEqual(key): Collection;
between(lower, upper, includeLower?, includeUpper?): Collection;
bulkAdd(items: Array): Promise;
bulkDelete(keys: Array): Promise;
bulkPut(items: Array): Promise;
clear(): Promise;
count(): Promise;
delete(key): Promise;
distinct(): Collection;
each(callback: (obj) => any): Promise;
eachKey(callback: (key) => any): Promise;
eachPrimaryKey(callback: (key) => any): Promise;
eachUniqueKey(callback: (key) => any): Promise;
equals(key): Collection;
equalsIgnoreCase(key): Collection;
filter(fn: (obj) => boolean): Collection;
first(): Promise;
get(key): Promise;
inAnyRange(ranges): Collection;
keys(): Promise;
last(): Promise;
limit(n: number): Collection;
modify(changeCallback: (obj: T, ctx:{value: T}) => void): Promise;
modify(changes: { [keyPath: string]: any } ): Promise;
noneOf(keys: Array): Collection;
notEqual(key): Collection;
offset(n: number): Collection;
or(indexOrPrimayKey: string): WhereClause;
orderBy(index: string): Collection;
primaryKeys(): Promise;
put(item: T, key?: Key): Promise;
reverse(): Collection;
sortBy(keyPath: string): Promise;
startsWith(key: string): Collection;
startsWithAnyOf(prefixes: string[]): Collection;
startsWithAnyOfIgnoreCase(prefixes: string[]): Collection;
startsWithIgnoreCase(key: string): Collection;
toArray(): Promise;
toCollection(): Collection;
uniqueKeys(): Promise;
until(filter: (value) => boolean, includeStopEntry?: boolean): Collection;
update(key: Key, changes: { [keyPath: string]: any }): Promise;
This is a mix of methods from WhereClause, Table and Collection. Dive into the API reference to see the details.
Dexie Cloud
Dexie Cloud is a commercial offering that can be used as an add-on to Dexie.js. It syncs a Dexie database with a server and enables developers to build apps without having to care about backend or database layer else than the frontend code with Dexie.js as the sole database layer.
Source for a sample Dexie Cloud app: Dexie Cloud To-do app
See the sample Dexie Cloud app in action: https://dexie.github.io/Dexie.js/dexie-cloud-todo-app/
Samples
https://dexie.org/docs/Samples
https://github.com/dexie/Dexie.js/tree/master/samples
Knowledge Base
https://dexie.org/docs/Questions-and-Answers
Website
Install via npm
npm install dexie
Download
For those who don't like package managers, here's the download links:
UMD (for legacy script includes as well as commonjs require):
https://unpkg.com/dexie@latest/dist/dexie.min.js
https://unpkg.com/dexie@latest/dist/dexie.min.js.map
Modern (ES module):
https://unpkg.com/dexie@latest/dist/modern/dexie.min.mjs
https://unpkg.com/dexie@latest/dist/modern/dexie.min.mjs.map
Typings:
https://unpkg.com/dexie@latest/dist/dexie.d.ts
Contributing
See CONTRIBUTING.md
Build
pnpm install
pnpm run build
Test
pnpm test
Watch
pnpm run watch
Top Related Projects
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.
Simple and fast JSON database
:kangaroo: - PouchDB is a pocket-sized database.
A fast, local first, reactive Database for JavaScript Applications https://rxdb.info/
:nut_and_bolt: A relentless key-value store for the browser.
The fastest and simplest library for SQLite3 in Node.js.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot