SQLite-Wasm im Browser, der vom ursprünglichen privaten Dateisystem gesichert wurde

Mit SQLite können Sie alle Ihre Speicheranforderungen im Web leistungsstark bewältigen.

SQLite ist ein beliebtes, Open-Source-System zur Verwaltung relationaler Datenbanken, das sich leicht einbetten lässt. Viele Entwickler verwenden es, um Daten auf strukturierte und nutzerfreundliche Weise zu speichern. Aufgrund seiner geringen Größe und der geringen Speicheranforderungen wird SQLite häufig als Datenbank-Engine auf Mobilgeräten, in Desktopanwendungen und Webbrowsern eingesetzt.

Eines der Hauptmerkmale von SQLite ist, dass es sich um eine serverlose Datenbank handelt, d. h., dass für die Ausführung kein separater Serverprozess erforderlich ist. Stattdessen wird die Datenbank in einer einzelnen Datei auf dem Gerät des Nutzers gespeichert, was die Einbindung in Anwendungen erleichtert.

SQLite-Logo

SQLite basierend auf Web Assembly

Es gibt eine Reihe inoffizieller SQLite-Versionen, die auf Web Assembly (Wasm) basieren und die Verwendung in Webbrowsern ermöglichen, z. B. sql.js. Das sqlite3 WASM/JS-Unterprojekt ist die erste Initiative, die offiziell mit dem SQLite-Projekt in Verbindung steht. Damit sind Wasm-Builds der Bibliothek nun Teil der unterstützten SQLite-Entwicklungsprodukte. Zu den konkreten Zielen dieses Projekts gehören:

  • Bindung einer untergeordneten sqlite3-API, die in Bezug auf die Verwendung so nah wie möglich an der C-API ist.
  • Eine objektorientierte API höherer Ebene, die eher mit sql.js und Implementierungen im Node.js-Stil vergleichbar ist und direkt mit der Low-Level-API kommuniziert. Diese API muss aus demselben Thread wie die Low-Level-API verwendet werden.
  • Eine Worker-basierte API, die über Worker-Nachrichten mit den vorherigen APIs kommuniziert. Diese API ist für die Verwendung im Haupt-Thread vorgesehen. Die APIs der unteren Ebene werden in einem Worker-Thread installiert und über Worker-Nachrichten mit ihnen kommuniziert.
  • Eine versprechensbasierte Variante der Worker API, die die aspekte der threadübergreifenden Kommunikation für den Nutzer vollständig verbirgt.
  • Unterstützung für persistenten clientseitigen Speicher mithilfe verfügbarer JavaScript APIs, einschließlich des Origin Private File Systems (OPFS).

SQLite Wasm mit dem Origin Private File System-Persistenz-Backend verwenden

Bibliothek über npm installieren

Installieren Sie das Paket @sqlite.org/sqlite-wasm von npm mit dem folgenden Befehl:

npm install @sqlite.org/sqlite-wasm

Origin Private File System

Das Origin Private File System (OPFS, Teil der File System Access API) wird durch eine spezielle Oberfläche ergänzt, die einen sehr leistungsfähigen Zugriff auf Daten ermöglicht. Diese neue Oberfläche unterscheidet sich von den vorhandenen Oberflächen dadurch, dass sie einen lokalen und exklusiven Schreibzugriff auf die Inhalte einer Datei bietet. Diese Änderung, die Möglichkeit, nicht gepufferte Änderungen konsistent zu lesen, und die Verfügbarkeit einer synchronen Variante auf dedizierten Workern verbessern die Leistung erheblich und ermöglichen neue Anwendungsfälle.

Wie Sie sich vorstellen können, ist der letzte Punkt der Projektziele, die Unterstützung für persistenten clientseitigen Speicher mithilfe der verfügbaren JavaScript APIs, mit strengen Leistungsanforderungen für das Speichern von Daten in der Datenbankdatei verbunden. Hier kommt das Origin Private File System und genauer gesagt die Methode createSyncAccessHandle() von FileSystemFileHandle-Objekten ins Spiel. Diese Methode gibt ein Promise zurück, das in ein FileSystemSyncAccessHandle-Objekt aufgelöst wird, mit dem Dateien synchron gelesen und geschrieben werden können. Die synchrone Ausführung dieser Methode bietet Leistungsvorteile, sie kann aber nur in speziellen Webworkern für Dateien im privaten Dateisystem von Origin verwendet werden, damit der Hauptthread nicht blockiert wird.

Erforderliche Header festlegen

Das heruntergeladene SQLite-Wasm-Archiv enthält unter anderem die Dateien sqlite3.js und sqlite3.wasm, die den sqlite3-Wasm/JS-Build bilden. Das Verzeichnis jswasm enthält die wichtigsten sqlite3-Ergebnisse und das übergeordnete Verzeichnis enthält Demo- und Test-Apps. Browser stellen keine Wasm-Dateien von file://-URLs bereit. Daher benötigen alle damit erstellten Apps einen Webserver. Dieser Server muss bei der Bereitstellung der Dateien die folgenden Header in die Antwort aufnehmen:

  • Cross-Origin-Opener-Policy ist auf die same-origin-Anweisung festgelegt, wodurch der Browserkontext ausschließlich auf Dokumente desselben Ursprungs beschränkt wird. Dokumente verschiedener Herkunft werden nicht im selben Browserkontext geladen.
  • Cross-Origin-Embedder-Policy ist auf die require-corp-Richtlinie festgelegt, sodass in einem Dokument nur Ressourcen aus demselben Ursprung oder Ressourcen geladen werden können, die ausdrücklich als von einem anderen Ursprung ladbar gekennzeichnet sind.

Der Grund für diese Header ist, dass SQLite Wasm von SharedArrayBuffer abhängt und die Einstellung dieser Header Teil der Sicherheitsanforderungen ist.

Wenn Sie den Traffic mit den Entwicklertools prüfen, sollten Sie die folgenden Informationen sehen:

Die beiden oben genannten Header „Cross-Origin-Embedder-Policy“ und „Cross-Origin-Opener-Policy“, hervorgehoben in den Chrome-Entwicklertools.

Geschwindigkeitstest

Das SQLite-Team hat einige Benchmarks für seine WebAssembly-Implementierung im Vergleich zur eingestellten Web SQL-Version durchgeführt. Diese Benchmarks zeigen, dass SQLite Wasm im Allgemeinen ungefähr so schnell ist wie Web SQL. Manchmal ist es etwas langsamer, manchmal etwas schneller. Alle Details finden Sie auf der Ergebnisseite.

Codebeispiel für den Einstieg

Wie bereits erwähnt, muss SQLite Wasm mit dem Origin Private File System-Persistenz-Backend in einem Worker-Kontext ausgeführt werden. Die gute Nachricht ist, dass die Bibliothek all das automatisch für Sie erledigt und Sie sie direkt über den Hauptthread verwenden können.

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

Demo

In der Demo können Sie sich den obigen Code in Aktion ansehen. Sehen Sie sich den Quellcode auf Glitch an. Beachten Sie, dass in der eingebetteten Version unten das OPFS-Backend nicht verwendet wird. Wenn Sie die Demo jedoch in einem separaten Tab öffnen, wird es verwendet.

Origin Private File System debuggen

Verwenden Sie die Chrome-Erweiterung OPFS Explorer, um die Ausgabe des Origin Private File Systems von SQLite Wasm zu debuggen.

OPFS Explorer im Chrome Web Store

Öffnen Sie nach der Installation der Erweiterung die Chrome-Entwicklertools und wählen Sie den Tab OPFS Explorer aus. Sie können dann prüfen, was SQLite Wasm in das Origin Private File System schreibt.

OPFS Explorer-Chrome-Erweiterung, die die Struktur des Origin Private File Systems der Demo-App zeigt

Wenn Sie eine der Dateien im OPFS Explorer-Fenster in den DevTools auswählen, können Sie sie auf dem lokalen Laufwerk speichern. Anschließend können Sie mit einer App wie SQLite Viewer die Datenbank prüfen, um sich zu vergewissern, dass SQLite Wasm tatsächlich wie versprochen funktioniert.

SQLite Viewer App, mit der eine Datenbankdatei aus der SQLite Wasm-Demo geöffnet wird.

Hilfe erhalten und Feedback geben

SQLite Wasm wird von der SQLite-Community entwickelt und gepflegt. Im Supportforum können Sie nach Antworten suchen und Feedback geben. Die vollständige Dokumentation finden Sie auf der SQLite-Website.