SQLite Wasm no navegador com suporte do sistema de arquivos particulares de origem

Use o SQLite para lidar com todas as suas necessidades de armazenamento com desempenho na Web.

O SQLite é um sistema de gerenciamento de banco de dados relacional leve, incorporado e de código aberto conhecido. Muitos desenvolvedores usam o SQLite para armazenar dados de maneira estruturada e fácil de usar. Devido ao tamanho pequeno e aos requisitos de memória baixos, o SQLite geralmente é usado como um mecanismo de banco de dados em dispositivos móveis, aplicativos para computador e navegadores da Web.

Uma das principais características do SQLite é que ele é um banco de dados sem servidor, o que significa que não requer um processo de servidor separado para operar. Em vez disso, o banco de dados é armazenado em um único arquivo no dispositivo do usuário, facilitando a integração com os aplicativos.

Logotipo do SQLite.

SQLite baseado na Web Assembly

Há várias versões não oficiais do SQLite baseadas na Web Assembly (Wasm), permitindo que ele seja usado em navegadores da Web, por exemplo, sql.js. O subprojeto sqlite3 WASM/JS é o primeiro esforço oficialmente associado ao projeto SQLite, fazendo com que os builds do Wasm da biblioteca sejam membros estabelecidos da família de itens de SQLite com suporte. Os objetivos concretos deste projeto incluem:

  • Vincular uma API sqlite3 de baixo nível que seja o mais próxima possível da API C em termos de uso.
  • Uma API orientada a objetos de nível mais alto, mais semelhante a sql.js e implementações no estilo Node.js, que se comunica diretamente com a API de baixo nível. Essa API precisa ser usada na mesma linha de execução da API de baixo nível.
  • Uma API baseada em worker que se comunica com as APIs anteriores por mensagens de worker. Essa é destinada ao uso na linha de execução principal, com as APIs de nível inferior instaladas em uma linha de execução de worker e se comunicando com elas por mensagens de worker.
  • Uma variante baseada em promessas da API Worker que oculta completamente os aspectos de comunicação entre linhas de execução do usuário.
  • Suporte para armazenamento persistente do lado do cliente usando APIs JavaScript disponíveis, incluindo o Origin Private File System (OPFS).

Como usar o SQLite Wasm com o back-end de persistência do sistema de arquivos particular da origem

Como instalar a biblioteca no npm

Instale o pacote @sqlite.org/sqlite-wasm do npm com o seguinte comando:

npm install @sqlite.org/sqlite-wasm

O sistema de arquivos particular da Origin

O Origin Private File System (OPFS, parte da API File System Access) é aprimorado com uma superfície especial que oferece acesso de alto desempenho aos dados. Essa nova plataforma difere das atuais por oferecer acesso de gravação exclusivo e no local ao conteúdo de um arquivo. Essa mudança, além da capacidade de ler modificações não limpas de forma consistente e a disponibilidade de uma variante síncrona em workers dedicados, melhora significativamente o desempenho e desbloqueia novos casos de uso.

Como você pode imaginar, o último ponto das metas do projeto, suporte a armazenamento persistente do lado do cliente usando APIs JavaScript disponíveis, vem com requisitos de desempenho rígidos em relação à persistência de dados no arquivo do banco de dados. É aqui que o Origin Private File System e, mais especificamente, o método createSyncAccessHandle() dos objetos FileSystemFileHandle entram em ação. Esse método retorna uma promessa que é resolvida para um objeto FileSystemSyncAccessHandle que pode ser usado para ler e gravar um arquivo de forma síncrona. A natureza síncrona desse método traz vantagens de desempenho, mas, portanto, ele só pode ser usado em Web Workers dedicados para arquivos no sistema de arquivos particular da origem, para que a linha de execução principal não seja bloqueada.

Como definir os cabeçalhos necessários

Entre outros arquivos, o arquivo SQLite Wasm baixado contém os arquivos sqlite3.js e sqlite3.wasm, que compõem o build sqlite3 WASM/JS. O diretório jswasm contém os principais resultados do sqlite3, e o diretório de nível superior contém apps de demonstração e teste. Os navegadores não vão oferecer arquivos Wasm de URLs file://. Portanto, todos os apps criados com isso exigem um servidor da Web, e esse servidor precisa incluir os seguintes cabeçalhos na resposta ao fornecer os arquivos:

O motivo desses cabeçalhos é que o SQLite Wasm depende de SharedArrayBuffer, e a configuração desses cabeçalhos faz parte dos requisitos de segurança.

Se você inspecionar o tráfego com as DevTools, vai encontrar as seguintes informações:

Os dois cabeçalhos mencionados acima, Cross-Origin-Embedder-Policy e Cross-Origin-Opener-Policy, destacados no Chrome DevTools.

Speedtest

A equipe do SQLite realizou alguns comparativos na implementação do WebAssembly em comparação com o SQL da Web descontinuado. Esses comparativos de mercado mostram que o SQLite Wasm é geralmente tão rápido quanto o Web SQL. Às vezes é um pouco mais lento, às vezes é um pouco mais rápido. Confira todos os detalhes na página de resultados.

Exemplo de código para começar

Como mencionado anteriormente, o SQLite Wasm com o back-end de persistência do sistema de arquivos particular da origem precisa ser executado em um contexto de worker. A boa notícia é que a biblioteca cuida automaticamente de tudo isso para você e pode ser usada diretamente na linha de execução 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);
  }
})();

Demonstração

Confira o código acima em ação na demonstração. Confira o código-fonte no Glitch. Observe como a versão incorporada abaixo não usa o back-end do OPFS, mas quando você abre a demonstração em uma guia separada, ele é usado.

Depurar o sistema de arquivos particular da origem

Para depurar a saída do sistema de arquivos particular de origem do SQLite Wasm, use a extensão OPFS Explorer do Chrome.

OPFS Explorer na Chrome Web Store.

Depois de instalar a extensão, abra o Chrome DevTools, selecione a guia OPFS Explorer e você estará pronto para inspecionar o que o SQLite Wasm grava no Origin Private File System.

Extensão do OPFS Explorer para Chrome mostrando a estrutura do Origin Private File System do app de demonstração.

Se você selecionar qualquer um dos arquivos na janela do OPFS Explorer no DevTools, poderá salvá-lo no disco local. Em seguida, use um app como o SQLite Viewer para inspecionar o banco de dados e garantir que o SQLite Wasm funciona conforme o esperado.

App SQLite Viewer usado para abrir um arquivo de banco de dados da demonstração do SQLite Wasm.

Receber ajuda e enviar feedback

O SQLite Wasm é desenvolvido e mantido pela comunidade SQLite. Receba ajuda e envie feedback pesquisando e postando no fórum de suporte. A documentação completa está disponível no site do SQLite.