Chrome扩展background.js中使用OPFS+SQLite WASM遇Worker未定义错误
核心问题分析
你遇到的Uncaught ReferenceError: Worker is not defined,根本原因是Manifest V3的background service worker本身属于Worker上下文,不支持Worker构造函数——普通页面里能创建子Worker,但Service Worker作为特殊的Worker环境,没有这个全局对象。
另外要明确:只有Worker类上下文(包括Service Worker、Dedicated Worker、Shared Worker)才能访问OPFS,Manifest V2的background page是普通浏览器页面,无法使用OPFS,所以必须用Manifest V3的service worker模式。
解决方案步骤
1. 确认Manifest配置正确(必须是V3)
确保你的manifest.json中background配置为service_worker,而非page,同时添加必要权限:
{ "manifest_version": 3, "name": "OPFS SQLite 扩展", "version": "1.0", "background": { "service_worker": "background.js" }, "permissions": ["storage"], "host_permissions": ["<all_urls>"] // 若需加载外部WASM资源则添加 }
2. 替换new Worker()的加载方式
在Service Worker中,不能创建子Worker,你有两种替代方案:
方案一:直接在background.js中执行原worker.js逻辑
把worker.js中的代码直接复制到background.js,或者用importScripts()加载脚本:// background.js importScripts('./worker.js'); // 加载原worker中的逻辑 // 直接初始化OPFS和SQLite async function initStorage() { // 获取OPFS根目录 const rootDir = await navigator.storage.getDirectory(); // 后续执行WASM SQLite初始化,比如打开OPFS中的数据库文件 // 示例(假设使用sqlite-wasm): const sqlite3 = await initSqlite3(); const db = new sqlite3.OPFSDB('mydb.db', rootDir); await db.open(); // 执行数据库操作... } initStorage();方案二:使用SharedWorker(可选)
如果你必须分离逻辑到独立Worker,可改用SharedWorker(Service Worker支持创建SharedWorker):// background.js const sharedWorker = new SharedWorker('./worker.js'); sharedWorker.port.onmessage = (e) => { // 处理Worker返回的数据 }; sharedWorker.port.postMessage('init');注意:SharedWorker的上下文同样支持OPFS,可在
worker.js中正常调用navigator.storage.getDirectory()。
3. 验证OPFS可用性
在Chrome扩展管理页面,点击你的扩展的"Service Worker"下的"Inspect",打开控制台执行:
navigator.storage.getDirectory().then(dir => console.log('OPFS可用', dir));
如果能输出目录对象,说明OPFS上下文正常。
关键注意事项
- 确保使用的WASM SQLite版本支持OPFS:比如官方的
sqlite-wasm提供了专门的OPFS适配模式,需启用该模式而非普通文件系统模式。 - 不要在Manifest V2中尝试OPFS:V2的background page属于普通页面,无OPFS访问权限。
- Service Worker会被Chrome自动休眠,若需长期保持连接,可使用
chrome.runtime.onMessage等事件唤醒。
内容的提问来源于stack exchange,提问作者Joseph Astrahan

