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

Usa SQLite para administrar todas tus necesidades de almacenamiento con rendimiento en la Web.

Información acerca de SQLite

SQLite es un sistema de administración de bases de datos relacionales popular, ligero de código abierto y, además, incorporado. Muchos desarrolladores lo utilizan para almacenar datos de una manera estructurada y fácil de usar. Debido a su tamaño pequeño y sus requisitos de memoria insuficiente, SQLite a menudo se aprovecha como un motor de base de datos en dispositivos móviles, aplicaciones de escritorio y navegadores web.

Una de las funciones clave de SQLite es que es una base de datos sin servidores, lo que significa que no requiere un proceso de servidor separado para funcionar. En cambio, la base de datos se almacena en un solo archivo en el dispositivo del usuario, lo que facilita la 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 utilizarla en navegadores web, por ejemplo, sql.js. El subproyecto WASM/JS de SQLite3 es el primer esfuerzo que se asocia oficialmente con el proyecto SQLite por lo que las compilaciones de Wasm de la biblioteca establecen miembros de la familia de entregables de SQLite compatibles. Los objetivos concretos de este proyecto incluyen los siguientes:

  • Vinculación de una API de Squarespace de bajo nivel que sea lo más similar 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 implementaciones de estilo Node.js, que se comunica directamente con la API de bajo nivel Esta API debe usarse 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. Este está diseñado para usarse en el subproceso principal, con las APIs de nivel inferior instaladas en un subproceso de trabajo, y para comunicarse con ellas a través de mensajes de trabajador.
  • Una variante basada en promesas de la API de Worker que oculta por completo al usuario los aspectos de la comunicación entre subprocesos.
  • Compatibilidad con almacenamiento persistente del cliente mediante 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 origen

Instala 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 origen

El sistema de archivos privados de origen (OPFS, que forma parte de la API de File System Access) está mejorado con una superficie especial que brinda un acceso de gran rendimiento a los datos. Esta plataforma nueva se diferencia de las existentes, ya que ofrece acceso de escritura exclusivo y local al contenido de los archivos. Este cambio, junto con la capacidad de leer de manera coherente las modificaciones no vacías 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, incluye requisitos de rendimiento estrictos con respecto a la persistencia de los datos en el archivo de la base de datos. Aquí es donde entra en juego el sistema de archivos privados de origen 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 en un archivo de forma síncrona. La naturaleza síncrona de este método aporta ventajas de rendimiento, pero, por lo tanto, solo se puede usar dentro de Web Workers dedicados para archivos dentro del sistema de archivos privados de origen, de modo que no se pueda bloquear el subproceso principal.

Configura los encabezados obligatorios

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

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

Si inspeccionas el tráfico con las Herramientas para desarrolladores, deberías encontrar la siguiente información:

Los dos encabezados mencionados anteriormente, Cross-Origin-Embedder-Policy y Cross-Origin-Opener-Policy, destacados en 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 obsoleto. Estas comparativas muestran que SQLite Wasm es, en general, tan rápido como Web SQL. A veces es un poco más lento, a veces es un poco más rápido. Consulta todos los detalles en la página de resultados.

Muestra de código de introducción

Como se mencionó anteriormente, SQLite Wasm con el backend de persistencia del sistema de archivos privados de origen debe ejecutarse desde un contexto de trabajador. La buena noticia es que la biblioteca se encarga de todo esto automáticamente y puedes usarla directamente 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

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

Cómo depurar el sistema de archivos privados de origen

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ás listo para inspeccionar lo que SQLite Wasm escribe en el sistema de archivos privados de origen.

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

Si haces clic en cualquiera de los archivos de la ventana del explorador de OPFS en Herramientas para desarrolladores, puedes guardarlo en el disco local. Luego, puedes usar una app como SQLite Viewer para inspeccionar la base de datos, de modo que puedas tener la certeza de que SQLite Wasm realmente funciona como se prometió.

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

Obtener ayuda y enviar comentarios

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

Agradecimientos

Hero image de Tobias Fischer en Unsplash.