在现代 Web 应用中,离线优先 (Offline-First) 已成为提升用户体验的关键策略。尤其是在网络环境不稳定的情况下,用户仍然可以访问和操作数据,并在网络恢复后自动同步。
PouchDB 和 Dexie.js 是 IndexedDB 生态中两款强大的库,结合它们可以构建一个高效、可扩展的离线优先同步方案。
在这篇文章中,我们将深入探讨:
需要高效的本地查询
find()
查询性能一般,适合基本查询,但 IndexedDB 查询较慢。需要离线存储和自动同步
本地缓存 + 远程同步的最佳实践
find()
可能够用。Dexie.js 是 IndexedDB 的封装库,提供高效的事务管理和查询优化。
import Dexie from "dexie";
// 定义本地数据库
class LocalDB extends Dexie {
items: Dexie.Table<{ id: string; data: any }, string>;
constructor() {
super("LocalDatabase");
this.version(1).stores({
items: "id", // 使用 id 作为主键
});
this.items = this.table("items");
}
}
const db = new LocalDB();
export default db;
PouchDB 允许我们存储数据在 IndexedDB,并支持远程 CouchDB 兼容数据库同步。
import PouchDB from "pouchdb";
import PouchFind from "pouchdb-find";
PouchDB.plugin(PouchFind);
// 创建本地数据库
const localDB = new PouchDB("local_database");
// 远程数据库(CouchDB 或兼容服务器)
const remoteDB = new PouchDB("http://your-server.com:5984/your-database");
// 监听数据库变化
localDB.changes({
since: "now",
live: true,
include_docs: true,
}).on("change", (change) => {
console.log("数据变更:", change);
});
async function saveItem(id: string, data: any) {
const doc = { _id: id, data };
// 存入 PouchDB(用于远程同步)
await localDB.put(doc);
// 存入 Dexie.js(提高本地查询速度)
await db.items.put({ id, data });
}
localDB.changes({
since: "now",
live: true,
include_docs: true,
}).on("change", async (change) => {
if (change.doc) {
await db.items.put({ id: change.doc._id, data: change.doc.data });
}
});
async function syncToDexie() {
const allDocs = await localDB.allDocs({ include_docs: true });
await db.items.clear(); // 清空本地 Dexie.js
for (const row of allDocs.rows) {
if (row.doc) {
await db.items.put({ id: row.doc._id, data: row.doc.data });
}
}
}
离线数据列表
- {{ item.data }}
如果你的应用需要 高效查询 + 离线优先同步,PouchDB + Dexie.js 绝对是一个值得尝试的方案!