Chrome 扩展开发:chrome.storage.local 对比 Indexeddb
Chrome extension development: chrome.storage.local vs Indexeddb
我目前正在开发一个数字钱包应用程序作为 chrome 扩展,并试图弄清楚我应该使用什么作为我的持久存储层:chrome.storage.local 或 indexedDb。我研究过其他类似的开源项目,似乎大多数使用前者而不是后者。
我想了解使用其中一个是否比另一个有任何优势。目前,我倾向于使用 chrome.storage.local 的原因是:
- 在官方chrome扩展文档API中建议作为存储API
- 它在应用重新启动后保持不变。 (Indexeddb 似乎也是,但我没有发现它在任何文档中被明确提及为持久存储,所以我不确定)
- 两者都是异步的
- 直截了当API(与 indexeddb 不同)
我知道我的用例和数据形状可能是一个重要因素:就我的应用而言
- 我正在存储简单的 JSON 类型(字符串、数字、布尔值、对象、数组)
- 对象数组可以任意长,例如存储地址列表或交易历史。 (这确实是让我思考 IndexedDb 是否会提供任何优势的主要原因)
基于以上所述,有什么理由可以证明一个比另一个更好地服务于我的应用程序?还有什么我应该考虑的吗?提前致谢!
在 Chrome 和 Firefox 中,扩展使用的 IndexedDB 是持久的。在 Chrome 中,即使不将 "unlimitedStorage"
添加到 "permissions"
中,它也是无限的,因此它使用全局配额管理,请参阅 crbug.com/1209236。我已经导入了一个虚拟的 40MB JSON(15MB 压缩)并且它有效。 Safari WebExtensions 规范可能不那么慷慨。
使用 IndexedDB 的原因:
- 非字符串 keys 和 values 受 structured clone algorithm (Map, Set, Date, RegExp, Blob, File, FileList, ArrayBuffer, ImageBitmap, ImageData, and recently BigInt 支持,Error)除了基本的 [=
chrome.storage.local
和 .sync
提供的 76=] 兼容类型(字符串、数字、布尔值、空值和 arrays/objects 递归地包含这些普通类型)。
- 存储和读取大型或深度嵌套的对象可能会快 10 倍甚至更多。
- 在不读取其值的情况下检查是否存在密钥。
- 只读取键的名称而不读取它们的值。
- 通过多个键建立索引。
- 为每个阵列投入整个
object store
(或很多),这些阵列可能会不可预测地增长或缩小。这比读取整个数组、修改它并写回 chrome.storage
. 中的单个键要快很多倍(如果数组很大,甚至可能是 1000)
扩展的 IndexedDB 不能直接在内容脚本中使用,只能通过解决方法:
消息传递。在 Chrome ManifestV2 中,它仅限于 JSON 兼容类型,因此要传输复杂类型,您必须将它们字符串化(慢)或通过 new Response
将数据转换为 Blob
,喂给URL.createObjectURL,发送结果URL,确认接收后撤销。 Chrome 的 ManifestV3 将支持消息的结构化克隆算法 soon 但它们的实现仍然在内部对克隆数据进行字符串化,因此在他们修复它之前处理大量数据肯定会很慢。
据我所知,Firefox 不受此限制。
网页中的 iframe src
指向通过 manifest.json 中的 web_accessible_resources
公开的扩展的 html 页面。这个 iframe (in Chrome) 运行s 在扩展过程中,所以它可以直接访问它的存储,并且它可以使用支持结构化克隆算法的 parent.postMessage 来发送结果。为避免被页面拦截,您应该 运行 您在 document_start 的内容脚本在页面执行之前以捕获模式附加监听器并防止其监听器看到事件:
// this script must be declared with "run-at": "document_start"
const extensionOrigin = chrome.runtime.getURL('').slice(0, -1);
window.addEventListener('message', e => {
if (e.origin === extensionOrigin) {
e.stopImmediatePropagation(); // hide from the page
console.log(e); // process the event
}
}, true); // register in the first phase, "capture"
但这还不够!站点可以在扩展之前安装监听器,因为 WebExtensions 实现中的基础安全漏洞(在 Chrome 和 Firefox 中观察到)允许页面修改新创建的同源 iframe 或 tab/window,请参阅 crbug.com/1261964,因此对于敏感的扩展,您必须实施非常复杂的解决方法,直到此漏洞被修补。希望 ManifestV3 将提供安全的 postMessage,仅限于内容脚本的“孤立世界”。
我目前正在开发一个数字钱包应用程序作为 chrome 扩展,并试图弄清楚我应该使用什么作为我的持久存储层:chrome.storage.local 或 indexedDb。我研究过其他类似的开源项目,似乎大多数使用前者而不是后者。
我想了解使用其中一个是否比另一个有任何优势。目前,我倾向于使用 chrome.storage.local 的原因是:
- 在官方chrome扩展文档API中建议作为存储API
- 它在应用重新启动后保持不变。 (Indexeddb 似乎也是,但我没有发现它在任何文档中被明确提及为持久存储,所以我不确定)
- 两者都是异步的
- 直截了当API(与 indexeddb 不同)
我知道我的用例和数据形状可能是一个重要因素:就我的应用而言
- 我正在存储简单的 JSON 类型(字符串、数字、布尔值、对象、数组)
- 对象数组可以任意长,例如存储地址列表或交易历史。 (这确实是让我思考 IndexedDb 是否会提供任何优势的主要原因)
基于以上所述,有什么理由可以证明一个比另一个更好地服务于我的应用程序?还有什么我应该考虑的吗?提前致谢!
在 Chrome 和 Firefox 中,扩展使用的 IndexedDB 是持久的。在 Chrome 中,即使不将 "unlimitedStorage"
添加到 "permissions"
中,它也是无限的,因此它使用全局配额管理,请参阅 crbug.com/1209236。我已经导入了一个虚拟的 40MB JSON(15MB 压缩)并且它有效。 Safari WebExtensions 规范可能不那么慷慨。
使用 IndexedDB 的原因:
- 非字符串 keys 和 values 受 structured clone algorithm (Map, Set, Date, RegExp, Blob, File, FileList, ArrayBuffer, ImageBitmap, ImageData, and recently BigInt 支持,Error)除了基本的 [=
chrome.storage.local
和.sync
提供的 76=] 兼容类型(字符串、数字、布尔值、空值和 arrays/objects 递归地包含这些普通类型)。 - 存储和读取大型或深度嵌套的对象可能会快 10 倍甚至更多。
- 在不读取其值的情况下检查是否存在密钥。
- 只读取键的名称而不读取它们的值。
- 通过多个键建立索引。
- 为每个阵列投入整个
object store
(或很多),这些阵列可能会不可预测地增长或缩小。这比读取整个数组、修改它并写回chrome.storage
. 中的单个键要快很多倍(如果数组很大,甚至可能是 1000)
扩展的 IndexedDB 不能直接在内容脚本中使用,只能通过解决方法:
消息传递。在 Chrome ManifestV2 中,它仅限于 JSON 兼容类型,因此要传输复杂类型,您必须将它们字符串化(慢)或通过
new Response
将数据转换为Blob
,喂给URL.createObjectURL,发送结果URL,确认接收后撤销。 Chrome 的 ManifestV3 将支持消息的结构化克隆算法 soon 但它们的实现仍然在内部对克隆数据进行字符串化,因此在他们修复它之前处理大量数据肯定会很慢。据我所知,Firefox 不受此限制。
网页中的 iframe
src
指向通过 manifest.json 中的web_accessible_resources
公开的扩展的 html 页面。这个 iframe (in Chrome) 运行s 在扩展过程中,所以它可以直接访问它的存储,并且它可以使用支持结构化克隆算法的 parent.postMessage 来发送结果。为避免被页面拦截,您应该 运行 您在 document_start 的内容脚本在页面执行之前以捕获模式附加监听器并防止其监听器看到事件:// this script must be declared with "run-at": "document_start" const extensionOrigin = chrome.runtime.getURL('').slice(0, -1); window.addEventListener('message', e => { if (e.origin === extensionOrigin) { e.stopImmediatePropagation(); // hide from the page console.log(e); // process the event } }, true); // register in the first phase, "capture"
但这还不够!站点可以在扩展之前安装监听器,因为 WebExtensions 实现中的基础安全漏洞(在 Chrome 和 Firefox 中观察到)允许页面修改新创建的同源 iframe 或 tab/window,请参阅 crbug.com/1261964,因此对于敏感的扩展,您必须实施非常复杂的解决方法,直到此漏洞被修补。希望 ManifestV3 将提供安全的 postMessage,仅限于内容脚本的“孤立世界”。