使用 SQLite 在网络上高效处理所有存储需求。
SQLite 是一种热门的开源轻量级嵌入式关系型数据库管理系统。许多开发者使用它以结构化且易于使用的方式存储数据。由于 SQLite 尺寸小且内存要求低,因此经常被用作移动设备、桌面应用和 Web 浏览器中的数据库引擎。
SQLite 的主要特点之一是它是一个无服务器数据库,这意味着它不需要单独的服务器进程即可运行。相反,该数据库存储在用户设备上的单个文件中,因此可以轻松集成到应用中。
基于 WebAssembly 的 SQLite
有许多基于 WebAssembly (Wasm) 的非官方 SQLite 版本,可用于 Web 浏览器,例如 sql.js。sqlite3 WASM/JS 子项目是首个与 SQLite 项目正式关联的项目,它使该库的 Wasm build 成为受支持的 SQLite 制品系列中的一员。此项目的具体目标包括:
- 绑定一个低级 sqlite3 API,该 API 在使用方面尽可能接近 C API。
- 一种更类似于 sql.js 和 Node.js 风格实现的高级面向对象 API,可直接与低级 API 通信。此 API 必须与低层级 API 使用相同的线程。
- 基于 Worker 的 API,可通过 Worker 消息与之前的 API 通信。此 API 旨在用于主线程,而较低级别的 API 安装在工作器线程中,并通过工作器消息与它们通信。
- 基于 Promise 的 Worker API 变体,可完全向用户隐藏跨线程通信方面的信息。
- 支持使用可用的 JavaScript API(包括 Origin Private File System [OPFS])进行持久性客户端存储。
将 SQLite Wasm 与源私有文件系统持久性后端搭配使用
从 npm 安装库
使用以下命令从 npm 安装 @sqlite.org/sqlite-wasm 软件包:
npm install @sqlite.org/sqlite-wasm
源私有文件系统
源私有文件系统 (OPFS,文件系统访问 API 的一部分) 经过增强,具有可实现高性能数据访问的特殊界面。此新 Surface 与现有 Surface 的不同之处在于,它提供对文件内容的就地独占写入访问权限。此项更改以及能够持续读取未刷新修改内容的功能,再加上专用工作器上同步变体的可用性,可显著提升性能并解锁新的使用情形。
正如您所想,项目目标的最后一点“使用可用的 JavaScript API 支持持久性客户端存储”对将数据持久保存到数据库文件提出了严格的性能要求。这时,源私有文件系统(更具体地说,FileSystemFileHandle
对象的 createSyncAccessHandle()
方法)就派上用场了。此方法会返回一个 Promise,该 Promise 会解析为一个 FileSystemSyncAccessHandle
对象,该对象可用于同步读取和写入文件。此方法的同步特性带来了性能优势,但因此只能在 Origin Private File System 中用于文件的专用 Web Worker 内使用,这样就不会阻塞主线程。
设置必需的标头
下载的 SQLite Wasm 归档文件包含 sqlite3.js
和 sqlite3.wasm
文件(以及其他文件),这些文件构成了 sqlite3 WASM/JS build。jswasm
目录包含核心 sqlite3 制品,而顶级目录包含演示应用和测试应用。浏览器不会从 file://
网址提供 Wasm 文件,因此您使用此功能构建的任何应用都需要 Web 服务器,并且该服务器在提供文件时必须在其响应中包含以下标头:
Cross-Origin-Opener-Policy
设置为same-origin
指令,该指令可将浏览上下文专门隔离到同源文档。跨源文档不会在同一浏览会话中加载。Cross-Origin-Embedder-Policy
设置为require-corp
指令,这样文档只能从同一来源加载资源,或者从明确标记为可从其他来源加载的资源加载资源。
设置这些标头的原因是,SQLite Wasm 依赖于 SharedArrayBuffer
,而设置这些标头是其安全要求的一部分。
如果您使用开发者工具检查流量,应该会发现以下信息:
Speedtest
SQLite 团队针对其 WebAssembly 实现与已弃用的 Web SQL 进行了基准比较。这些基准测试表明,SQLite Wasm 的速度通常与 Web SQL 相当。有时会慢一点,有时会快一点。如需查看所有详细信息,请前往结果页面。
入门代码示例
如前所述,使用 Origin Private File System 持久性后端的 SQLite Wasm 需要从 Worker 上下文中运行。好消息是,该库会自动为您处理所有这些问题,您可以直接从主线程中使用它。
import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';
(async () => {
try {
console.log('Loading and initializing SQLite3 module...');
const promiser = await new Promise((resolve) => {
const _promiser = sqlite3Worker1Promiser({
onready: () => {
resolve(_promiser);
},
});
});
console.log('Done initializing. Running demo...');
let response;
response = await promiser('config-get', {});
console.log('Running SQLite3 version', response.result.version.libVersion);
response = await promiser('open', {
filename: 'file:worker-promiser.sqlite3?vfs=opfs',
});
const { dbId } = response;
console.log(
'OPFS is available, created persisted database at',
response.result.filename.replace(/^file:(.*?)\?vfs=opfs$/, '$1'),
);
await promiser('exec', { dbId, sql: 'CREATE TABLE IF NOT EXISTS t(a,b)' });
console.log('Creating a table...');
console.log('Insert some data using exec()...');
for (let i = 20; i <= 25; ++i) {
await promiser('exec', {
dbId,
sql: 'INSERT INTO t(a,b) VALUES (?,?)',
bind: [i, i * 2],
});
}
console.log('Query data with exec()');
await promiser('exec', {
dbId,
sql: 'SELECT a FROM t ORDER BY a LIMIT 3',
callback: (result) => {
if (!result.row) {
return;
}
console.log(result.row);
},
});
await promiser('close', { dbId });
} catch (err) {
if (!(err instanceof Error)) {
err = new Error(err.result.message);
}
console.error(err.name, err.message);
}
})();
演示
如需查看上述代码的实际效果,请参阅演示。 请务必查看 GitHub 上的源代码。请注意,下面的嵌入式版本未使用 OPFS 后端,但当您在单独的标签页中打开演示时,它会使用 OPFS 后端。
调试源私有文件系统
如需调试 SQLite Wasm 的源站专用文件系统输出,请使用 OPFS Explorer Chrome 扩展程序。
安装扩展程序后,打开 Chrome 开发者工具,选择 OPFS Explorer 标签页,然后即可检查 SQLite Wasm 写入到 Origin Private File System 的内容。
如果您在开发者工具的 OPFS 资源管理器窗口中选择任何文件,则可以将其保存到本地磁盘。然后,您可以使用 SQLite Viewer 等应用检查数据库,从而确保 SQLite Wasm 确实按承诺的那样运行。
获取帮助和提供反馈
SQLite Wasm 由 SQLite 社区开发和维护。在支持论坛中搜索和发帖,获取帮助并提供反馈。如需查看完整文档,请访问 SQLite 网站。