使用 Dexie.js 构建支持离线功能的渐进式 Web 应用 (PWA)
Dexie.js 是一个高效的 IndexedDB 封装库,能够简化 IndexedDB 的操作,特别适合用于渐进式 Web 应用(PWA)的离线数据存储功能。以下是使用 Dexie.js 实现支持离线功能的完整指导:
1. 初始化项目
- 创建 PWA 项目:使用框架如 Vue、React、或者直接用 HTML/CSS/JS。
- 设置 Service Worker:
- 注册 Service Worker 以缓存静态资源(HTML、CSS、JS)。
- 配置缓存策略以支持离线加载。
2. 安装 Dexie.js
在项目中安装 Dexie.js:
npm install dexie
或者通过 <script>
标签引入:
<script src="https://cdn.jsdelivr.net/npm/dexie@latest/dist/dexie.min.js"></script>
3. 配置 Dexie 数据库
创建一个用于存储离线数据的数据库。以下是一个示例代码:
import Dexie from 'dexie';
// 初始化数据库
const db = new Dexie('MyAppDatabase');
// 定义数据库结构
db.version(1).stores({
todos: '++id, title, completed', // 自增 ID, 任务标题, 是否完成
users: 'id, name, email' // 主键 ID, 用户名, 邮箱
});
// 示例:添加初始数据
db.on('populate', () => {
db.todos.bulkAdd([
{ title: 'Learn Dexie.js', completed: false },
{ title: 'Build a PWA', completed: true },
]);
});
db.open().catch((err) => {
console.error("Failed to open the database:", err);
});
export default db;
4. 实现离线存储功能
4.1 同步离线数据
离线时可以将用户的操作记录到数据库中,当重新联网时,将数据同步到服务器。
async function saveTodoOffline(todo) {
try {
await db.todos.add(todo);
console.log('Todo saved locally');
} catch (error) {
console.error('Failed to save todo:', error);
}
}
4.2 获取离线数据
通过 Dexie 从 IndexedDB 中读取数据:
async function fetchTodos() {
try {
const todos = await db.todos.toArray();
console.log('Fetched todos:', todos);
return todos;
} catch (error) {
console.error('Failed to fetch todos:', error);
}
}
4.3 同步到服务器
当网络恢复时,将离线存储的数据同步到服务器:
async function syncTodosToServer() {
const todos = await db.todos.toArray();
for (const todo of todos) {
try {
// 发送数据到服务器
await fetch('/api/todos', {
method: 'POST',
body: JSON.stringify(todo),
headers: { 'Content-Type': 'application/json' },
});
// 同步成功后删除本地存储
await db.todos.delete(todo.id);
} catch (error) {
console.error('Failed to sync todo:', error);
}
}
}
5. 配置 Service Worker
确保你的 PWA 可以离线访问数据和功能。
示例 Service Worker 配置:
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open('static-cache-v1').then((cache) => {
return cache.addAll([
'/',
'/index.html',
'/styles.css',
'/app.js',
]);
})
);
});
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
6. 将 Dexie 与前端集成
在你的前端应用中,与 Dexie 数据库交互以管理离线和在线数据。例如:
import db from './db';
// 添加任务
async function addTodo(title) {
await saveTodoOffline({ title, completed: false });
}
// 显示任务
async function displayTodos() {
const todos = await fetchTodos();
const todoList = document.getElementById('todo-list');
todos.forEach(todo => {
const listItem = document.createElement('li');
listItem.textContent = `${todo.title} - ${todo.completed ? 'Completed' : 'Pending'}`;
todoList.appendChild(listItem);
});
}
// 初始化
document.addEventListener('DOMContentLoaded', () => {
displayTodos();
});
7. 测试和部署
- 测试离线功能:
- 断开网络连接,确保 PWA 可以正常加载并操作离线数据。
- 恢复网络后,验证数据同步是否正确。
- 部署:
- 部署到支持 HTTPS 的服务器(PWA 要求 HTTPS)。
总结
利用 Dexie.js 和 PWA 技术,可以轻松实现以下功能:
- 离线数据存储:在无网络时保存用户操作。
- 数据同步:网络恢复后,将本地数据同步到服务器。
- 优化用户体验:即使没有网络,也能使用应用的主要功能。
这种方案特别适用于需要高可用性、跨设备操作的应用,如任务管理、电子商务和数据收集平台。