Langsung ke konten utama

Alternatif @capacitor-community/sqlite di 2026

Mencari alternatif untuk @capacitor-community/sqlite? Bandingkan dengan Capgo Fast SQL dan migrasikan Capacitor SQLite code serta data pengguna Anda langkah demi langkah.

logo Capgo untuk panduan alternatif plugin SQLite komunitas Capacitor

Alternatif utama untuk @capacitor-community/sqlite di Capacitor 8 adalah @capgo/capacitor-fast-sql: plugin SQLite native untuk iOS, Android, dan web yang menjaga SQLCipher tetap opsional dan mengirim data query lewat kanal HTTP lokal, bukan lewat bridge Capacitor. Panduan ini membandingkan keduanya secara jujur, menjelaskan kapan sebaiknya tetap pakai plugin komunitas, dan memandu migrasi code maupun database pengguna yang sudah ada.

Mengapa tim mencari alternatif

@capacitor-community/sqlite telah menjadi plugin SQLite default untuk Capacitor selama bertahun-tahun dan masih dikelola (8.1.1 rilis Agustus 2026). Alasan orang berpindah sangat spesifik:

  1. Serialisasi bridge. Setiap hasil melewati bridge Capacitor sebagai JSON. Itu tidak masalah untuk query kecil, tapi terasa saat memuat ribuan baris untuk sinkronisasi atau pencarian.
  2. SQLCipher selalu disertakan. Plugin ini bergantung pada SQLCipher di iOS dan Android meskipun Anda tidak pernah mengenkripsi. Itu menambah ukuran native dan berarti binary Anda berisi code enkripsi yang harus Anda perhitungkan dalam jawaban kepatuhan ekspor.
  3. Model penyimpanan web. Di web, plugin ini menggunakan jeep-sqlite komponen: sql.js di memori, disimpan ke IndexedDB saat Anda memanggil saveToStore(). Anda harus ingat untuk menyimpannya, dan seluruh database berada di memori.
  4. Cakupan API yang besar. Connection wrappers, consistency checks, koneksi read-only dan non-conformed, sync tables, import dan export JSON. Powerful, tapi banyak yang harus dipelajari untuk sekadar “run SQL”.
  5. Satu passphrase per app. Enkripsi menggunakan satu secret yang disimpan oleh plugin (setEncryptionSecret), yang dibagikan ke semua database terenkripsi dalam app.

Perbandingan berdampingan

@capacitor-community/sqlite 8.1 @capgo/capacitor-fast-sql 8.2
Platform iOS, Android, Web, Electron iOS, Android, Web
Path data bridge Capacitor Server HTTP lokal dengan token per koneksi (native)
Mesin web jeep-sqlite (sql.js + IndexedDB, manual saveToStore) Resmi @sqlite.org/sqlite-wasm dengan OPFS, penulisan diarahkan ke file
Enkripsi SQLCipher selalu dibundel, satu passphrase yang dikelola plugin SQLCipher opsional, kunci dilewatkan per database saat aktif connect()
Swift Package Manager Ya (Package.swift) Ya (Package.swift)
Schema versioning upgradeStatements / addUpgradeStatement Milik Anda sendiri, biasanya PRAGMA user_version
Impor/ekspor JSON, sinkronisasi tabel Ya Tidak
Database terisi awal dari aset copyFromAssets() Salin file Anda sendiri sebelumnya connect()
Helper key-value Tidak KeyValueStore
BLOB Ya Ya, sebagai Uint8Array
Dukungan ORM TypeORM bawaan capacitor driver Driver kustom (Kysely bekerja dengan baik)
Setup native tambahan Web: salin sql-wasm.wasm iOS NSAllowsLocalNetworking, aturan cleartext localhost Android
Maintainer komunitas Capacitor Capgo

Kapan sebaiknya tetap pakai plugin komunitas

Jadilah praktis. Tetap gunakan jika:

  • Anda merilis Electron build,
  • you use TypeORM (driver capacitor-nya ditulis untuk plugin komunitas, lihat TypeORM dengan Capacitor),
  • yang kamu andalkan import/export JSON atau sinkronisasi tabel dan tidak ingin membangun ulang aplikasi tersebut,
  • query Anda kecil dan aplikasi berjalan baik saat ini.

Kapan Fast SQL lebih cocok

Pindah jika:

  • Anda memuat atau menulis dataset besar (sync engine, katalog offline, indeks pencarian, log CRDT),
  • Anda ingin enkripsi hanya untuk beberapa database, dengan kunci dari Keychain atau Keystore,
  • Anda tidak perlu menggunakan SQLCipher pada aplikasi yang tidak membutuhkannya.
  • Anda ingin file SQLite asli di web melalui OPFS, bukan salinan in-memory,
  • Anda ingin API yang sederhana: connect, query, run, transaction.

Untuk walkthrough lengkap tentang Fast SQL itu sendiri, lihat Cara menggunakan SQLite di aplikasi Capacitor.

Langkah 1: instal Fast SQL berdampingan dengan plugin lama

Biarkan plugin komunitas tetap terpasang untuk satu rilis agar Anda dapat memigrasikan data yang sudah ada.

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

Konfigurasi native yang dibutuhkan Fast SQL:

  • iOS: NSAppTransportSecurity > NSAllowsLocalNetworking = true di Info.plist.
  • Android: network_security_config.xml yang mengizinkan cleartext ke localhost dan 127.0.0.1, yang dirujuk dari manifest.
  • Enkripsi: net.zetetic:sqlcipher-android di modul aplikasi Android dan CapgoCapacitorFastSql/SQLCipher pod di iOS. Detail di enkripsi SQLite di Capacitor.
  • Web: Cross-Origin-Opener-Policy: same-origin dan Cross-Origin-Embedder-Policy: require-corp headers untuk OPFS.

Langkah 2: petakan API

Membuka database

Sebelum:

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

Sesudah:

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

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

FastSQL.connect() mengembalikan koneksi yang ada jika database sudah terbuka, jadi tidak perlu isConnection / retrieveConnection ribet.

Pemetaan method

Plugin komunitas SQL Cepat
createConnection() + open() FastSQL.connect({ database })
closeConnection(name) FastSQL.disconnect(name)
db.query(sql, values) mengembalikan { values } db.query(sql, params) mengembalikan baris
db.run(sql, values) mengembalikan { changes: { changes, lastId } } db.run(sql, params) mengembalikan { rowsAffected, insertId }
db.execute(multiStatementString) Satu db.execute(sql) per statement, atau db.executeBatch([...])
db.executeSet(set) db.executeBatch(ops) dengan { statement, params }
beginTransaction / commitTransaction / rollbackTransaction db.transaction(async (tx) => ...) atau beginTransaction() / commit() / rollback()
addUpgradeStatement / upgradeStatements Sebuah PRAGMA user_version migration runner
copyFromAssets() Salin bundle .db ke dalam Directory.Data sebelum pertama kali connect()
setEncryptionSecret() + mode: 'secret' encrypted: true, encryptionKey aktif connect()
initWebStore() / saveToStore() Tidak perlu, OPFS mempertahankan penulisan

Query dan penulisan

Sebelum:

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;

Sesudah:

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

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

Kedua plugin mengembalikan baris sebagai objek yang dikey berdasarkan nama kolom.

Eksekusi multi-statement

The community execute() menerima string dengan beberapa statement yang dipisahkan oleh ;. Fast SQL menyiapkan satu statement per panggilan. Pisahkan SQL Anda, atau lebih baik lagi, simpan statement sebagai 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 })));

Jangan pisahkan berdasarkan ; dengan cara naif split(';') jika ada statement yang berisi body trigger atau string literal dengan titik koma.

Upgrade statement ke user_version

Plugin komunitas menyimpan versi schema di PRAGMA user_version juga. Jika Anda tetap memakai nomor versi yang sama, database pengguna yang sudah ada sudah berada di versi yang benar setelah migrasi file di langkah 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}`);
    });
  }
}

Periksa nilai aktual user_version pada instalasi yang sudah ada sebelum mengandalkan ini. Log nilainya dari plugin lama di rilis Anda saat ini jika Anda tidak yakin.

Database yang sudah terisi

milik plugin komunitas copyFromAssets() menyalin database yang dibundel saat peluncuran pertama. Dengan Fast SQL, letakkan file di tempat yang dicari plugin sebelum terhubung. Fast SQL menyimpan <name>.db di Documents di iOS dan di direktori aplikasi files directory on Android, which are both Directory.Data di @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 });
}

Untuk file besar, unduh dalam chunk atau kirim file terkompresi dan gunakan native copy dari file plugin alih-alih base64 di JavaScript.

Langkah 3: migrasi data pengguna yang ada

Pengguna yang memperbarui aplikasi Anda memiliki database yang dibuat oleh plugin community. Database ini berada di path yang berbeda dengan nama yang berbeda:

Plugin komunitas SQL Cepat
iOS Documents/<name>SQLite.db (default iosDatabaseLocation) Documents/<name>.db
Android databases/<name>SQLite.db files/<name>.db

Opsi A: salin file (database tanpa enkripsi)

Tercepat, dan mempertahankan semuanya: index, 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' });
}

Panggil sebelum pertama kali FastSQL.connect({ database: name }). Catatan:

  • getUrl() (iOS dan Android) mengembalikan URL file database. Mengirimkan file:// URL lengkap tanpa directory memungkinkan plugin Filesystem membaca dari jalur apa pun di dalam sandbox Anda.
  • Menutup koneksi dan melakukan checkpoint terlebih dahulu memastikan tidak ada penulisan terbaru yang tertinggal di -wal Anda.
  • Simpan file lama untuk satu rilis, lalu hapus nanti dengan koneksi komunitas delete() metode koneksi komunitas setelah Anda yakin. Lalu hapus plugin komunitas.

Opsi B: salin baris di JavaScript (database terenkripsi, atau perubahan skema)

Ketika sumber dienkripsi dengan secret yang disimpan oleh plugin komunitas, jalur aman paling sederhana adalah membiarkan plugin tersebut mendekripsi dan menyalin baris ke database Fast SQL baru. Ini juga memungkinkan Anda mengenkripsi dengan kunci per-database baru dari 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);
  }
}

Gunakan 'no-encryption' dan false di createConnection jika sumber tidak dienkripsi. Plugin komunitas membutuhkan iosIsEncryption / androidIsEncryption di capacitor.config untuk mode terenkripsinya, yang sudah Anda miliki jika pernah menggunakannya. Untuk tabel besar, lakukan paging dengan WHERE rowid > ? ORDER BY rowid LIMIT 5000.

Kedua plugin menggunakan default SQLCipher 4, sehingga file terenkripsi juga bisa dibuka langsung di Fast SQL dengan passphrase yang sama. Namun, plugin komunitas mengelola passphrase tersebut secara internal, dan menyalin baris menghindari ketergantungan pada detail itu.

Langkah 4: hapus plugin lama

Setelah satu atau dua rilis dengan migrasi yang sudah diterapkan:

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

Hapus sql-wasm.wasm dari aset Anda dan jeep-sqlite setup dalam main.ts. Menghapus plugin juga menghapus dependensi SQLCipher-nya, jadi jika Anda tidak mengaktifkan enkripsi Fast SQL, biner iOS dan Android menjadi lebih kecil.

Migrasi data code adalah JavaScript, jadi bisa dikirim bersama Live updates Capgo, tetapi rilis yang menambahkan Fast SQL adalah perubahan native dan membutuhkan build store. Kirim build native terlebih dahulu. Build Capgo dapat menghasilkannya di cloud jika Anda tidak memiliki Mac (upload App Store membutuhkan Xcode 26 atau lebih baru sejak April 2026).

Pemecahan Masalah

Fast SQL terhubung tetapi setiap query gagal di iOS. NSAllowsLocalNetworking tidak ada di aplikasi Info.plist, atau aplikasi tidak di-rebuild setelah menambahkannya.

Android: CLEARTEXT communication to localhost not permitted. Tambahkan localhost domain-config ke konfigurasi keamanan jaringan Anda. Jika sudah ada untuk SSL pinning, gabungkan keduanya.

Hanya sebagian skema saya yang dibuat. Anda mengirim string multi-statement ke execute(). Pecah menjadi array.

INSERT ... RETURNING tidak mengembalikan apa pun di Android. Di Fast SQL 8.2, Android hanya mengembalikan baris untuk statement yang diawali dengan SELECT, PRAGMA atau EXPLAIN. Gunakan insertId dari run().

Boolean tidak cocok saat dibaca di Android. Gunakan 1/0 alih-alih true/false di parameter query. Android mengikat parameter read-query sebagai teks.

Database yang disalin kosong. Plugin komunitas dikonfigurasi dengan custom iosDatabaseLocation, atau nama sumber berbeda. Log URL yang dikembalikan oleh getUrl().

Data web dari plugin lama hilang. Plugin komunitas menyimpan data web di IndexedDB melalui jeep-sqlite, Fast SQL menggunakan OPFS. Sinkronkan ulang klien web dari backend Anda, atau ekspor dengan exportToJson dari plugin lama dan impor baris ke Fast SQL.

Opsi lainnya

  • @capgo/capacitor-data-storage-sqlite jika yang benar-benar Anda butuhkan adalah penyimpanan key-value berbasis string yang didukung SQLite. Lihat penyimpanan key-value di Capacitor.
  • ORM atau query builder di atasnya: Kysely berfungsi dengan Fast SQL melalui driver kustom singkat. Drizzle saat ini lebih cocok dengan plugin komunitas.

Fast SQL lengkap API ada di dokumentasi plugin dan di halaman plugin.

Live updates untuk aplikasi Capacitor

Saat bug web-layer sudah live, kirim perbaikannya lewat Capgo alih-alih menunggu berhari-hari untuk persetujuan app store. Pengguna mendapat update di background, sementara perubahan native tetap mengikuti jalur review normal.

Terbaru dari Blog kami

Capgo memberikan insight terbaik yang Anda butuhkan untuk membuat aplikasi mobile yang benar-benar profesional.