由源私有文件系统提供支持的浏览器中的 SQLite Wasm

使用 SQLite 在网络上高效地处理所有存储需求。

SQLite 简介

SQLite 是一个广受欢迎的开源轻量级嵌入式关系型数据库管理系统。许多开发者使用它以结构化且易于使用的方式存储数据。由于其体积较小且内存要求较低,SQLite 通常用作移动设备、桌面应用和网络浏览器中的数据库引擎。

SQLite 的一个关键特性是它是一个无服务器数据库,这意味着它不需要单独的服务器进程即可运行。而是将数据库存储在用户设备上的单个文件中,以便轻松集成到应用中。

SQLite 徽标。

基于 Web Assembly 的 SQLite

有多个基于 Web Assembly (Wasm) 的非官方 SQLite 版本可供在网络浏览器中使用,例如 sql.jssqlite3 WASM/JS 子项目是与 SQLite 项目正式关联的首个项目,该项目是受支持的 SQLite 交付项系列中建立的库成员的 Wasm build。此项目的具体目标包括:

  • 绑定一个低级别 sqlite3 API,该 API 在使用方面尽可能接近 C 语言。
  • 一个面向对象的更高级别 API,更类似于 sql.jsNode.js 样式的实现,直接与低级别 API 对话。必须在与低级别 API 相同的线程中使用此 API。
  • 基于 worker 的 API,通过 worker 消息与之前的 API 对话。此 API 适用于主线程,较低级别的 API 安装在工作器线程中,并通过工作器消息与这些 API 通信。
  • 基于 Promise 的 Worker API 变体,完全对用户隐藏跨线程通信方面。
  • 支持使用可用的 JavaScript API(包括源私有文件系统 (OPFS))的永久性客户端存储。

将 SQLite Wasm 与源私有文件系统持久性后端搭配使用

从 npm 安装库

使用以下命令从 npm 安装 @sqlite.org/sqlite-wasm 软件包:

npm install @sqlite.org/sqlite-wasm

源私有文件系统

源私有文件系统(OPFS,是 File System Access API 的一部分)经过增强,具有一个特殊的 Surface,可以实现高性能数据访问。此新 surface 与现有 surface 不同,因为它提供对文件内容的就地和独占写入访问权限。此更改,以及始终读取未刷新的修改以及专用工作器上同步变体的可用性,显著提高了性能并解锁了新的用例。

您可以想象,项目目标的最后一点是支持使用可用的 JavaScript API 的永久性客户端存储,对于将数据保存到数据库文件具有严格的性能要求。这正是源私有文件系统的用武之地,更具体地说,就是 FileSystemFileHandle 对象的 createSyncAccessHandle() 方法。此方法会返回一个解析为 FileSystemSyncAccessHandle 对象(可用于对文件进行同步读取和写入的 Promise)。此方法的同步性质可提升性能,因此只能在专用 Web Worker 内使用源私有文件系统中的文件,因此主线程无法被阻塞。

设置所需的标头

下载的 SQLite Wasm 归档文件除了包含其他文件外,还包含 sqlite3.jssqlite3.wasm 文件,它们构成了 sqlite3 WASM/JS build。jswasm 目录包含核心 sqlite3 交付项,顶层目录包含演示和测试应用。浏览器不会从 file:// 网址传送 Wasm 文件,因此您使用它构建的所有应用都需要 Web 服务器,并且在传送文件时,该服务器必须在其响应中添加以下标头:

之所以使用这些头文件,是因为 SQLite Wasm 依赖于 SharedArrayBuffer,而设置这些头文件是其安全要求的一部分。

如果您使用开发者工具检查流量,应该会找到以下信息:

在 Chrome 开发者工具中突出显示的上述两个标头:Cross-Origin-Embedder-Policy 和 Cross-Origin-Opener-Policy。

速度测试

与已废弃的 Web SQL 相比,SQLite 团队已对其 WebAssembly 实现运行了一些基准测试。这些基准测试表明,SQLite Wasm 的速度通常与 Web SQL 一样快。有时速度会稍慢一些 有时速度会快一些在结果页面上查看所有详细信息。

入门代码示例

如前所述,包含源私有文件系统持久性后端的 SQLite Wasm 需要从工作器上下文运行。好消息是,该库会自动为您处理所有这些操作,您可以直接从主线程使用它。

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);
  }
})();

演示

演示中查看上述代码的实际运行情况。请务必查看 Glitch 上的源代码。请注意,下面的嵌入式版本不使用 OPFS 后端,但当您在单独的标签页中打开演示时,它会使用。

调试源私有文件系统

如需调试 SQLite Wasm 的源私有文件系统输出,请使用 OPFS Explorer Chrome 扩展程序。

Chrome 应用商店中的 OPFS Explorer。

安装扩展程序后,打开 Chrome 开发者工具,选择 OPFS Explorer 标签页,然后您就可以检查 SQLite Wasm 写入源私有文件系统的内容了。

显示演示版应用的 Origin Private File System 结构的 OPFS Explorer Chrome 扩展程序。

如果您在开发者工具的 OPFS Explorer 窗口中点击任何文件,则可以将其保存到本地磁盘。然后,您可以使用 SQLite Viewer 等应用来检查数据库,确保 SQLite Wasm 实际上按预期运行。

SQLite 查看器应用,用于从 SQLite Wasm 演示中打开数据库文件。

获取帮助和提供反馈

SQLite Wasm 由 SQLite 社区开发和维护。您可以搜索支持论坛并在其中发帖,以获取帮助和提供反馈。SQLite 网站上提供了完整的文档

致谢

主打图片,由 Tobias Fischer 发布,来源是 Unsplash 用户。