Yjs IndexedDB Persistence
y-indexeddb is a database adapter for Yjs, providing robust persistence for Yjs documents directly within the browser's IndexedDB. It enables critical features such as offline editing and significantly reduces the amount of data exchanged between a server and client by storing the full document state locally. The package is actively maintained, with the current stable version being 9.0.12, and receives frequent patch and minor updates. Its primary differentiation lies in its tight integration with the Yjs ecosystem, offering reliable CRDT-based persistence for collaborative applications without requiring a separate server-side database, making it ideal for browser-based, offline-first applications leveraging Yjs.
Common errors
-
TypeError: IndexeddbPersistence is not a constructor
cause Incorrect module import syntax, typically trying to use CommonJS `require()` with a package that primarily exposes ESM, or an incorrect named import.fixUse ESM import syntax: `import { IndexeddbPersistence } from 'y-indexeddb';`. Ensure your environment supports ESM or use a bundler that transpiles it correctly. If using TypeScript, check `tsconfig.json` for `moduleResolution` settings. -
Unhandled Promise Rejection Warning: Promise { <pending> } (or similar unhandled promise error) when calling clearData()cause The `clearData()` method, since v9.0.6, returns a Promise, but it is not being awaited or explicitly handled.fixAlways `await` calls to `provider.clearData()` within an `async` function, or handle the Promise using `.then().catch()`.
Warnings
- breaking The `clearData()` method now returns a Promise. Calls to `clearData()` must be awaited to ensure the operation completes and to catch potential errors.
- breaking The package introduced an `exports` field in `package.json` in v9.0.12. This change primarily affects how module resolvers (especially older ones or specific CommonJS setups) locate the package's entry points. While designed to improve ESM compatibility, it might lead to import resolution issues for projects still heavily relying on `require()` in environments not fully compliant with modern module resolution.
- gotcha The `IndexeddbPersistence` provider automatically calls its `destroy()` method when its associated Yjs document (`ydoc`) is destroyed (e.g., via `ydoc.destroy()`). Manually calling `provider.destroy()` immediately after or before `ydoc.destroy()` can be redundant or lead to unexpected behavior if lifecycle hooks are involved.
- gotcha The package has a peer dependency on `yjs`. Ensure that the installed `yjs` version is compatible with `y-indexeddb` to avoid runtime errors or unexpected synchronization issues.
Install
-
npm install y-indexeddb -
yarn add y-indexeddb -
pnpm add y-indexeddb
Imports
- IndexeddbPersistence
const IndexeddbPersistence = require('y-indexeddb').IndexeddbPersistence;import { IndexeddbPersistence } from 'y-indexeddb'; - IndexeddbPersistence (TypeScript Type)
import type { IndexeddbPersistence } from 'y-indexeddb';
Quickstart
import * as Y from 'yjs';
import { IndexeddbPersistence } from 'y-indexeddb';
const ydoc = new Y.Doc();
const docName = 'my-shared-document';
// Create a provider for IndexedDB persistence
const provider = new IndexeddbPersistence(docName, ydoc);
provider.on('synced', async () => {
console.log('Content from the database is loaded.');
// After content is loaded, you can safely interact with ydoc
if (ydoc.getText('myText').length === 0) {
ydoc.getText('myText').insert(0, 'Hello Yjs and IndexedDB!');
console.log('Initial text set:', ydoc.getText('myText').toString());
} else {
console.log('Loaded text:', ydoc.getText('myText').toString());
}
// Example of storing custom metadata
await provider.set('lastEdited', Date.now());
console.log('Metadata stored:', await provider.get('lastEdited'));
});
// Clean up resources when the document is no longer needed
// Note: provider.destroy() is often automatically called if ydoc.destroy() is used.
// For demonstration, manually destroying after a delay:
// setTimeout(() => {
// provider.destroy();
// console.log('IndexedDB persistence destroyed.');
// }, 5000);