SQLite Wasm en el navegador respaldado por el sistema de archivos privados de origen

Usa SQLite para controlar todas tus necesidades de almacenamiento de manera eficiente en la Web.

SQLite es un sistema de administración de bases de datos relacionales de código abierto, ligero y empotrable. Muchos desarrolladores lo usan para almacenar datos de forma estructurada y fácil de usar. Debido a su tamaño pequeño y sus requisitos de memoria mínimos, SQLite a menudo se aprovecha como motor de base de datos en dispositivos móviles, aplicaciones para computadoras de escritorio y navegadores web.

Una de las características clave de SQLite es que es una base de datos sin servidor, lo que significa que no requiere un proceso de servidor independiente para funcionar. En cambio, la base de datos se almacena en un solo archivo en el dispositivo del usuario, lo que facilita su integración en las aplicaciones.

Logotipo de SQLite.

SQLite basado en Web Assembly

Existen varias versiones no oficiales de SQLite basadas en Web Assembly (Wasm), que permiten usarla en navegadores web, por ejemplo, sql.js. El subproyecto sqlite3 WASM/JS es el primer esfuerzo que se asocia oficialmente con el proyecto SQLite, lo que hace que las compilaciones de Wasm de la biblioteca sean miembros establecidos de la familia de entregas compatibles de SQLite. Entre los objetivos concretos de este proyecto, se incluyen los siguientes:

  • Vincula una API de sqlite3 de bajo nivel que sea lo más cercana posible a la de C en términos de uso.
  • Una API orientada a objetos de nivel superior, más similar a sql.js y a las implementaciones de estilo de Node.js, que se comunica directamente con la API de bajo nivel. Esta API se debe usar desde el mismo subproceso que la API de bajo nivel.
  • Una API basada en trabajadores que se comunica con las APIs anteriores a través de mensajes de trabajadores. Esta está diseñada para usarse en el subproceso principal, con las APIs de nivel inferior instaladas en un subproceso de trabajo y comunicarse con ellas a través de mensajes de trabajador.
  • Es una variante de la API de Worker basada en promesas que oculta por completo los aspectos de comunicación entre subprocesos al usuario.
  • Compatibilidad con el almacenamiento persistente del cliente con las APIs de JavaScript disponibles, incluido el sistema de archivos privados de origen (OPFS).

Cómo usar SQLite Wasm con el backend de persistencia del sistema de archivos privados de Origin

Cómo instalar la biblioteca desde npm

Instala el paquete @sqlite.org/sqlite-wasm desde npm con el siguiente comando:

npm install @sqlite.org/sqlite-wasm

El sistema de archivos privados de Origin

El sistema de archivos privados de Origin (OPFS, parte de la API de acceso al sistema de archivos) se complementa con una plataforma especial que brinda acceso a los datos con un rendimiento muy alto. Esta nueva plataforma difiere de las existentes, ya que ofrece acceso de escritura exclusivo y en el lugar al contenido de un archivo. Este cambio, junto con la capacidad de leer de forma coherente las modificaciones no borradas y la disponibilidad de una variante síncrona en los trabajadores dedicados, mejora significativamente el rendimiento y desbloquea nuevos casos de uso.

Como puedes imaginar, el último punto de los objetivos del proyecto, la compatibilidad con el almacenamiento persistente del cliente mediante las APIs de JavaScript disponibles, tiene requisitos de rendimiento estrictos en cuanto a la persistencia de datos en el archivo de la base de datos. Aquí es donde entra en juego el sistema de archivos privados de Origin y, más específicamente, el método createSyncAccessHandle() de los objetos FileSystemFileHandle. Este método muestra una promesa que se resuelve en un objeto FileSystemSyncAccessHandle que se puede usar para leer y escribir de forma síncrona en un archivo. La naturaleza síncrona de este método brinda ventajas de rendimiento, pero solo se puede usar dentro de trabajadores web dedicados para archivos dentro del sistema de archivos privados de origen, de modo que no se pueda bloquear el subproceso principal.

Cómo configurar los encabezados obligatorios

Entre otros archivos, el archivo SQLite Wasm descargado contiene los archivos sqlite3.js y sqlite3.wasm, que conforman la compilación de WASM/JS de sqlite3. El directorio jswasm contiene las entregas principales de sqlite3, y el directorio de nivel superior contiene apps de demostración y prueba. Los navegadores no entregarán archivos Wasm desde URLs file://, por lo que las apps que compilas con esto requieren un servidor web, y ese servidor debe incluir los siguientes encabezados en su respuesta cuando entregue los archivos:

El motivo de estos encabezados es que SQLite Wasm depende de SharedArrayBuffer, y configurar estos encabezados es parte de sus requisitos de seguridad.

Si inspeccionas el tráfico con DevTools, deberías encontrar la siguiente información:

Los dos encabezados mencionados anteriormente, Cross-Origin-Embedder-Policy y Cross-Origin-Opener-Policy, destacados en las Herramientas para desarrolladores de Chrome

Prueba de velocidad

El equipo de SQLite ejecutó algunas comparativas en su implementación de WebAssembly en comparación con Web SQL, que dejó de estar disponible. Estas comparativas muestran que SQLite Wasm es, en general, tan rápido como Web SQL. A veces es un poco más lento y, a veces, un poco más rápido. Consulta todos los detalles en la página de resultados.

Ejemplo de código de introducción

Como se mencionó anteriormente, SQLite Wasm con el backend de persistencia del sistema de archivos privados de Origin debe ejecutarse desde un contexto de trabajador. La buena noticia es que la biblioteca se encarga automáticamente de todo esto por ti y puedes usarla desde el subproceso principal.

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

Demostración

Consulta el código anterior en acción en la demostración. Asegúrate de revisar el código fuente en Glitch. Observa que la versión incorporada que se muestra a continuación no usa el backend de OPFS, pero sí lo hace cuando abres la demostración en una pestaña separada.

Cómo depurar el sistema de archivos privados de Origin

Para depurar el resultado del sistema de archivos privados de origen de SQLite Wasm, usa la extensión de Chrome OPFS Explorer.

OPFS Explorer en Chrome Web Store.

Después de instalar la extensión, abre las Herramientas para desarrolladores de Chrome, selecciona la pestaña OPFS Explorer y estará todo listo para inspeccionar lo que SQLite Wasm escribe en el sistema de archivos privados de origen.

Extensión de Chrome de OPFS Explorer que muestra la estructura del sistema de archivos privados de Origin de la app de demostración.

Si seleccionas cualquiera de los archivos de la ventana del explorador de OPFS en DevTools, puedes guardarlo en el disco local. Luego, puedes usar una app como SQLite Viewer para inspeccionar la base de datos y asegurarte de que SQLite Wasm funcione como se prometió.

App de SQLite Viewer que se usa para abrir un archivo de base de datos de la demostración de SQLite Wasm.

Cómo obtener ayuda y enviar comentarios

La comunidad de SQLite desarrolla y mantiene SQLite Wasm. Para obtener ayuda y enviar comentarios, busca en el foro de asistencia y publica en él. La documentación completa está disponible en el sitio de SQLite.