__CAPGO_KEEP_0__ home

Alternativa a @capacitor-community/sqlite nel 2026

Stai cercando un'alternativa a @capacitor-community/sqlite? Confrontala con Capgo Fast SQL e migra i tuoi Capacitor SQLite code e i dati degli utenti passo dopo passo.

Alternativa a @capacitor-community/sqlite nel 2026

La principale alternativa a @capacitor-community/sqlite su Capacitor 8 è @capgo/capacitor-fast-sql: un plugin SQLite nativo per iOS, Android e il web che mantiene SQLCipher facoltativo e invia i dati delle query attraverso un canale HTTP locale anziché il ponte Capacitor. Questa guida confronta le due onestamente, dice quando restare sulla plugin della community e guida attraverso la migrazione sia dei tuoi code che dei database degli utenti esistenti.

Why le squadre cercano un'alternativa

@capacitor-community/sqlite è stato il plugin SQLite predefinito per Capacitor per anni e viene ancora mantenuto (8.1.1 rilasciato nel agosto 2026). Le ragioni per cui le persone si spostano sono specifiche:

  1. Serializzazione del Bridge. Tutti i risultati passano attraverso il bridge di Capacitor come JSON. Ciò è accettabile per piccole query, e notevole quando si caricano migliaia di righe per la sincronizzazione o la ricerca.
  2. SQLCipher è sempre incluso. Il plugin dipende da SQLCipher su iOS e Android anche se non si crittografano mai. Ciò aggiunge dimensioni native e significa che il tuo binario contiene crittografia code che devi tenere conto nelle risposte di compliance all'esportazione.
  3. Modello di archiviazione web. Sul web utilizza il componente: sql.js in memoria, persistito in IndexedDB quando si chiama jeep-sqlite Devi ricordarti di salvare, e l'intera database vive in memoria. saveToStore()Ricordate di salvare e il database intero vive nella memoria.
  4. Una grande superficie API. Raccoglitori di connessioni, controlli di consistenza, connessioni di sola lettura e non conformi, tabelle sincrone, importazione ed esportazione JSON. Potente, ma molto da imparare per "eseguire SQL".
  5. Una frase segreta per app. L'encryption utilizza un segreto singolo memorizzato dal plugin (setEncryptionSecret), condiviso da ogni database crittografato nell'app.

Confronto a faccia a faccia

@capacitor-community/sqlite 8.1 @capgo/capacitor-fast-sql 8.2
Piattaforme iOS, Android, Web, Electron iOS, Android, Web
Percorso dei dati ponte Capacitor Server HTTP locale con un token per connessione (nativo)
Motore web jeep-sqlite (sql.js + IndexedDB, manuale saveToStore) Ufficiale @sqlite.org/sqlite-wasm con OPFS, le scritture vanno nel file
Criptazione SQLCipher sempre inclusa, una passphrase gestita da plugin SQLCipher facoltativo, chiave passata per database su connect()
Manager dei Pacchetti Swift Sì (Package.swift) Sì (Package.swift)
Versione dello schema upgradeStatements / addUpgradeStatement La tua, di solito PRAGMA user_version
Importazione/Esportazione JSON, sincronizzazione delle tabelle Sì No
Database prepopolato da asset copyFromAssets() Copia il file prima di connect()
Assistente chiave-valore No KeyValueStore
BLOB Sì Sì, come Uint8Array
Sostegno ORM Driver integrato TypeORM capacitor driver Driveri personalizzati (Kysely funziona bene)
Configurazione nativa aggiuntiva Copia: web sql-wasm.wasm iOS NSAllowsLocalNetworking, regola localhost cleartext per Android
Responsabile comunità di Capacitor Capgo

Quando mantenere il plugin della community

hai distribuito un

  • Electron costruisci costruisci,
  • Utilizzate TypeORM (il suo capacitor driver è scritto contro il plugin della community, vedi TypeORM con Capacitor),
  • Relyete import/export o sincronizzazione di tabelle e non volete ricostruirle,
  • Le vostre query sono piccole e l'app funziona bene oggi.

Quando Fast SQL è la scelta migliore

Muovete se:

  • Caricate o scrivete grandi set di dati (motori di sincronizzazione, cataloghi offline, indici di ricerca, registri CRDT),
  • Volete l'encryption solo per alcune database, con chiavi dal Keychain o Keystore,
  • non desiderate SQLCipher in un'applicazione che non ne ha bisogno
  • desiderate un file SQLite reale sul web attraverso OPFS al posto di una copia in memoria
  • desiderate un semplice API: connettersi, interrogare, eseguire, transazione.

Per una guida completa di Fast SQL stesso, vedere Come utilizzare SQLite in un'app Capacitor.

Passo 1: installare Fast SQL accanto al vecchio plugin

Conservate installato il plugin della community per una versione per poter migrare i dati esistenti.

bun add @capgo/capacitor-fast-sql
bunx cap sync

Configurazione nativa che Fast SQL richiede:

  • iOS: NSAppTransportSecurity > NSAllowsLocalNetworking = true in Info.plist.
  • Android: a network_security_config.xml che consente il testo chiaro localhost e 127.0.0.1, riferito dal manifesto.
  • Criptazione: net.zetetic:sqlcipher-android nel modulo dell'app Android e nel CapgoCapacitorFastSql/SQLCipher pod su iOS. Dettagli in criptare SQLite in Capacitor.
  • Web: Cross-Origin-Opener-Policy: same-origin e Cross-Origin-Embedder-Policy: require-corp intestazioni per OPFS.

Passo 2: mappa il API

Aprire una banca dati

Prima:

import { CapacitorSQLite, SQLiteConnection } from '@capacitor-community/sqlite';

const sqlite = new SQLiteConnection(CapacitorSQLite);
const db = await sqlite.createConnection('app', false, 'no-encryption', 1, false);
await db.open();

Dopo:

import { FastSQL } from '@capgo/capacitor-fast-sql';

const db = await FastSQL.connect({ database: 'app', walMode: true, performancePresets: true });

FastSQL.connect() restituisce la connessione esistente se la banca dati è già aperta, quindi non ci sono isConnection / retrieveConnection dance.

Mappatura del metodo

Plugin della comunità SQL veloce
createConnection() + open() FastSQL.connect({ database })
closeConnection(name) FastSQL.disconnect(name)
db.query(sql, values) restituisce { values } db.query(sql, params) restituisce righe
db.run(sql, values) restituisce { changes: { changes, lastId } } db.run(sql, params) restituisce { rowsAffected, insertId }
db.execute(multiStatementString) One db.execute(sql) per statement, o db.executeBatch([...])
db.executeSet(set) db.executeBatch(ops) con { statement, params }
beginTransaction / commitTransaction / rollbackTransaction db.transaction(async (tx) => ...) o beginTransaction() / commit() / rollback()
addUpgradeStatement / upgradeStatements Una PRAGMA user_version un migratore di migrazione
copyFromAssets() Copia un pacchetto .db into Directory.Data prima della prima connect()
setEncryptionSecret() + mode: 'secret' encrypted: true, encryptionKey on connect()
initWebStore() / saveToStore() Non necessario, OPFS persiste le scritture

Copy a bundled

Prima:

const res = await db.query('SELECT * FROM notes WHERE pinned = ?', [1]);
const notes = res.values ?? [];

const { changes } = await db.run('INSERT INTO notes (title) VALUES (?)', ['Hello']);
const id = changes?.lastId;

Dopo:

const notes = await db.query('SELECT * FROM notes WHERE pinned = ?', [1]);

const { insertId } = await db.run('INSERT INTO notes (title) VALUES (?)', ['Hello']);

Entrambi i plugin restituiscono le righe come oggetti chiave nome colonna.

Esecuzione multi-statement

La comunità execute() accetta una stringa con più istruzioni separate da ;Fast SQL prepara una istruzione per chiamata. Spegna la tua SQL, o meglio, conserva le istruzioni come array:

const schema = [
  'CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL)',
  'CREATE INDEX IF NOT EXISTS idx_notes_title ON notes (title)',
];

await db.executeBatch(schema.map((statement) => ({ statement })));

Non dividere su ; con un approccio ingenuo split(';') se qualsiasi istruzione contiene un corpo di trigger o una stringa letterale con un punto e virgola.

Aggiorna le dichiarazioni di upgrade a user_version

Il plugin della comunità memorizza la versione dello schema in PRAGMA user_version Se mantenete gli stessi numeri di versione, i database dei vostri utenti esistenti sono già alla versione giusta dopo la migrazione del file nel passo 3.

import type { SQLConnection } from '@capgo/capacitor-fast-sql';

// Same content as your old upgrade statements, index 0 = version 1
const versions: string[][] = [
  ['CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL)'],
  ['ALTER TABLE notes ADD COLUMN pinned INTEGER NOT NULL DEFAULT 0'],
];

export async function migrate(db: SQLConnection) {
  const [{ user_version }] = await db.query('PRAGMA user_version');
  for (let v = Number(user_version); v < versions.length; v++) {
    await db.transaction(async (tx) => {
      for (const statement of versions[v]) await tx.execute(statement);
      await tx.execute(`PRAGMA user_version = ${v + 1}`);
    });
  }
}

Controlla l'effettivo user_version Sul tuo installazione esistente prima di affidarti a questo. Registra il messaggio dall'antico plugin nella tua versione corrente se non sei sicuro.

Databases prepopolate

La plugin della comunità copyFromAssets() Copia le database bundle alla prima esecuzione. Con Fast SQL, posiziona il file dove il plugin lo cerca prima di connettersi. Fast SQL memorizza <name>.db in Documents in iOS e nell'applicazione files directory su Android, che sono entrambi Directory.Data in @capacitor/filesystem:

import { Directory, Filesystem } from '@capacitor/filesystem';
import { FastSQL } from '@capgo/capacitor-fast-sql';

async function openCatalog() {
  const exists = await Filesystem.stat({ path: 'catalog.db', directory: Directory.Data })
    .then(() => true)
    .catch(() => false);

  if (!exists) {
    const blob = await (await fetch('/assets/catalog.db')).blob();
    const base64 = await new Promise<string>((resolve) => {
      const reader = new FileReader();
      reader.onloadend = () => resolve((reader.result as string).split(',')[1]);
      reader.readAsDataURL(blob);
    });
    await Filesystem.writeFile({ path: 'catalog.db', data: base64, directory: Directory.Data });
  }
  return FastSQL.connect({ database: 'catalog', readOnly: true });
}

Per i file grandi, scaricali in chunk o invia un file compresso e utilizza il plugin di file nativo per copiare al posto di base64 in JavaScript.

Passo 3: migra i dati degli utenti esistenti

Utenti che aggiornano l'applicazione hanno una banca dati creata dal plugin della community. Vive in un percorso diverso con un nome diverso:

Plugin della community SQL veloce
iOS Documents/<name>SQLite.db (default iosDatabaseLocation) Documents/<name>.db
Android databases/<name>SQLite.db files/<name>.db

Opzione A: copia il file (banche dati non crittografate)

Più veloce e mantiene tutto: indici, trigger, user_version.

import { CapacitorSQLite, SQLiteConnection } from '@capacitor-community/sqlite';
import { Directory, Filesystem } from '@capacitor/filesystem';
import { Preferences } from '@capacitor/preferences';

export async function moveCommunityDatabase(name: string): Promise<void> {
  const done = await Preferences.get({ key: `sqlite-moved:${name}` });
  if (done.value === '1') return;

  const sqlite = new SQLiteConnection(CapacitorSQLite);
  const exists = (await sqlite.isDatabase(name)).result;
  if (exists) {
    const conn = await sqlite.createConnection(name, false, 'no-encryption', 1, false);
    await conn.open();
    await conn.execute('PRAGMA wal_checkpoint(TRUNCATE)', false).catch(() => undefined);
    const { url } = await conn.getUrl();
    await sqlite.closeConnection(name, false);

    if (url) {
      await Filesystem.copy({ from: url, to: `${name}.db`, toDirectory: Directory.Data });
    }
  }
  await Preferences.set({ key: `sqlite-moved:${name}`, value: '1' });
}

Chiamalo prima della prima FastSQL.connect({ database: name }). Note:

  • getUrl() Ritorna l'URL del file di database (iOS e Android). Passa un file di database completo file:// __CAPGO_KEEP_0__ directory consente al plugin Filesystem di leggere da qualsiasi percorso all'interno del tuo sandbox.
  • Chiudendo la connessione e effettuando il checkpoint prima si assicura che nessuna scrittura recente sia lasciata in un -wal file.
  • Mantieni il file vecchio per una versione e cancellalo in seguito con la connessione della community delete() Opzione B: copia righe in JavaScript (database criptati, o un cambiamento di schema)

Opzione B: copia righe in JavaScript (database crittografate, o un cambiamento di schema)

When the source is encrypted with the community plugin’s stored secret, the simplest safe path is to let that plugin decrypt and copy rows into a new Fast SQL database. This also lets you encrypt with a new per-database key from secure storage.

import { CapacitorSQLite, SQLiteConnection } from '@capacitor-community/sqlite';
import { FastSQL } from '@capgo/capacitor-fast-sql';
import { Preferences } from '@capacitor/preferences';

export async function copyRows(name: string, target: { encryptionKey?: string }) {
  // Record which destination mode was migrated, so a later call with a different target fails loudly
  const mode = target.encryptionKey ? 'encrypted' : 'plain';
  const done = await Preferences.get({ key: `sqlite-copied:${name}` });
  if (done.value === mode) return;
  if (done.value) throw new Error(`${name} was already copied as ${done.value}, not ${mode}`);

  const sqlite = new SQLiteConnection(CapacitorSQLite);
  const src = await sqlite.createConnection(name, true, 'secret', 1, false);
  await src.open();

  try {
    const dst = await FastSQL.connect({
      database: name,
      encrypted: Boolean(target.encryptionKey),
      encryptionKey: target.encryptionKey,
    });

    const objects = ((await src.query(
      `SELECT type, name, sql FROM sqlite_master
       WHERE sql IS NOT NULL AND name NOT LIKE 'sqlite_%'`,
    )).values ?? []) as { type: string; name: string; sql: string }[];
    const tables = objects.filter((o) => o.type === 'table');
    const others = objects.filter((o) => o.type !== 'table');
    const version = (await src.query('PRAGMA user_version')).values?.[0]?.user_version ?? 0;

    await dst.transaction(async (tx) => {
      for (const t of tables) await tx.execute(t.sql);
      for (const t of tables) {
        const rows = (await src.query(`SELECT * FROM "${t.name}"`)).values ?? [];
        if (!rows.length) continue;
        const cols = Object.keys(rows[0]);
        const statement = `INSERT INTO "${t.name}" (${cols.map((c) => `"${c}"`).join(', ')}) VALUES (${cols.map(() => '?').join(', ')})`;
        await tx.executeBatch(rows.map((r) => ({ statement, params: cols.map((c) => r[c]) })));
      }
      for (const o of others) await tx.execute(o.sql);
      await tx.execute(`PRAGMA user_version = ${Number(version)}`);
    });

    // Only mark the copy as done once the transaction has committed
    await Preferences.set({ key: `sqlite-copied:${name}`, value: mode });
  } finally {
    await sqlite.closeConnection(name, false);
  }
}

e 'no-encryption' in false in createConnection se la fonte non è crittografata. Il plugin della community richiede iosIsEncryption / androidIsEncryption in capacitor.config per le sue modalità crittografate, che già avete se le avete utilizzate. Per le grandi tabelle, passate pagina con WHERE rowid > ? ORDER BY rowid LIMIT 5000.

Entrambi i plugin utilizzano SQLCipher 4 di default, quindi un file crittografato può anche essere aperto direttamente in Fast SQL con la stessa passphrase. Il plugin della community gestisce internamente quella passphrase, e la copia di riga evita di dipendere da quel dettaglio.

Passo 4: rimuovi l'antico plugin

Dopo uno o due rilasci con la migrazione in atto:

bun remove @capacitor-community/sqlite jeep-sqlite
bunx cap sync

Rimuovi sql-wasm.wasm dai tuoi asset e da qualsiasi jeep-sqlite impostazione di main.ts. La rimozione del plugin elimina anche la sua dipendenza da SQLCipher, quindi se non opti per l'encryption di Fast SQL, i binari iOS e Android diventano più piccoli.

La migrazione dei dati code è JavaScript, quindi può essere spedita con Capgo aggiornamenti livema la release che aggiunge Fast SQL è un cambiamento nativo e richiede una build del store. Invia la build nativa per prima. Capgo Build puoi produrlo in cloud se non hai un Mac a portata di mano (le pubblicazioni su App Store richiedono Xcode 26 o successivi dal 2026).

Troubleshooting

Fast SQL si connette ma ogni query fallisce su iOS. NSAllowsLocalNetworking è assente nell'applicazione Info.plisto l'app non è stata ricostruita dopo averlo aggiunto.

Android: CLEARTEXT communication to localhost not permitted. Aggiungi il localhost domain-config Aggiungi la configurazione di sicurezza della rete al tuo setup. Se già avevi una configurazione per la pinning SSL, uniscile.

Hai passato una stringa multi-statement a Hai passato una stringa multi-statement a execute()non restituisce nulla su Android.

INSERT ... RETURNING Risoluzione dei problemi In Fast SQL 8.2, Android restituisce righe solo per le dichiarazioni che iniziano con SELECT, PRAGMA o EXPLAIN. Utilizza insertId da run().

Booleani non corrispondono su letture Android. Passa 1/0 al posto di true/false Parametri di query. Android lega i parametri di query di lettura come testo.

La copia del database è vuota. Il plugin della community è stato configurato con un custom iosDatabaseLocation, o il nome della fonte differisce. Registra l'URL restituito da getUrl().

Dati web dall'antica plugin sono andati perduti. The community plugin memorizzava i dati web in IndexedDB attraverso jeep-sqlite, Fast SQL utilizza OPFS. Ri-sincronizza i client web dal tuo backend, o esporta con il vecchio plugin's exportToJson e importa righe in Fast SQL.

Altre opzioni

  • @capgo/capacitor-data-storage-sqlite se ciò che veramente hai bisogno è un archivio chiavi-valori supportato da SQLite. Vedi archiviazione chiavi-valori in Capacitor.
  • Un ORM o costruttore di query sopra: Kysely funziona con Fast SQL attraverso un breve driver personalizzato. Drizzle attualmente si adatta meglio al plugin della community.

La full Fast SQL API è in il plugin docs e sul pagina plugin.

Aggiornamenti in tempo reale per le app Capacitor

Quando un bug nel layer web è attivo, invia la correzione attraverso Capgo invece di attendere giorni per l'approvazione della store. Gli utenti ricevono l'aggiornamento in background mentre le modifiche native rimangono nel normale percorso di revisione.

Ultimi articoli dal nostro Blog

Capgo offre le migliori informazioni che ti servono per creare un'app mobile davvero professionale.