Chrome扩展向SQLite存储数据的实现方案问询
解决方案:MV3扩展中用SQLite WASM存储活跃标签页内容
核心限制说明
Chrome MV3的background是Service Worker,它无法直接创建Web Worker(这是已知限制),所以得换个思路:把SQLite WASM的逻辑放在独立的Offscreen页面里,通过Service Worker和Offscreen页面通信来完成存储操作。
实现步骤
1. 扩展配置(manifest.json)
先声明offscreen权限及必要的标签页、存储权限:
{ "manifest_version": 3, "name": "Tab SQLite Saver", "version": "1.0", "background": { "service_worker": "background.js" }, "permissions": ["tabs", "activeTab", "offscreen"], "host_permissions": ["<all_urls>"] }
2. Offscreen页面(offscreen.html & offscreen.js)
Offscreen页面可正常使用Web Worker和OPFS,用来托管SQLite WASM逻辑:
offscreen.html
<!DOCTYPE html> <html> <body> <script src="offscreen.js"></script> </body> </html>
offscreen.js
初始化SQLite WASM,监听来自background的消息并处理存储:
// 加载SQLite WASM(需将sqlite3.js、sqlite3.wasm放入扩展目录) import { sqlite3Worker1Promiser } from './sqlite3.js'; let db; // 初始化数据库 async function initDB() { const sqlite3 = await sqlite3Worker1Promiser(); // 用OPFS创建持久化数据库 db = await sqlite3.open({ filename: 'tab-history.db', opfs: true }); // 创建标签页存储表 await db.exec(` CREATE TABLE IF NOT EXISTS tabs ( id INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT, title TEXT, timestamp INTEGER, active BOOLEAN ); `); } // 接收background的存储请求 chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => { if (message.type === 'SAVE_TAB') { if (!db) await initDB(); // 插入标签页数据 await db.run(` INSERT INTO tabs (url, title, timestamp, active) VALUES (?, ?, ?, ?); `, [message.tab.url, message.tab.title, Date.now(), true]); sendResponse({ success: true }); } }); // 页面加载时初始化数据库 initDB();
3. Background Service Worker(background.js)
监听活跃标签页变化,向Offscreen页面发送存储请求:
// 确保Offscreen页面已启动 async function ensureOffscreenDocument() { if (await chrome.offscreen.hasDocument()) return; await chrome.offscreen.createDocument({ url: 'offscreen.html', reasons: ['LOCAL_STORAGE'], justification: 'Store tab data to SQLite via OPFS' }); } // 监听活跃标签页切换 chrome.tabs.onActivated.addListener(async (activeInfo) => { await ensureOffscreenDocument(); const tab = await chrome.tabs.get(activeInfo.tabId); chrome.runtime.sendMessage({ type: 'SAVE_TAB', tab: { url: tab.url, title: tab.title } }); }); // 监听标签页加载完成,保存更新后的内容 chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { if (changeInfo.status === 'complete' && tab.active) { await ensureOffscreenDocument(); chrome.runtime.sendMessage({ type: 'SAVE_TAB', tab: { url: tab.url, title: tab.title } }); } });
4. 注意事项
- 需从SQLite官方获取预编译的WASM包(sqlite3.js、sqlite3.wasm),放入扩展目录。
- OPFS需要安全上下文,扩展内部页面默认满足,无需额外配置。
- 消息通信时注意数据序列化,不要传递无法序列化的对象。
内容的提问来源于stack exchange,提问作者Vince
相关产品推荐
相关产品推荐

