Alternatif utama untuk @capacitor-community/sqlite pada Capacitor 8 adalah @capgo/capacitor-fast-sql: plugin SQLite asli untuk iOS, Android, dan web yang menjaga SQLCipher optional dan mengirimkan data kueri melalui saluran HTTP lokal daripada jembatan Capacitor. Panduan ini membandingkan dua hal secara jujur, mengatakan kapan harus tetap menggunakan plugin komunitas, dan menjelajahi migrasi baik code maupun database pengguna Anda.
Why tim team mencari alternatif
@capacitor-community/sqlite telah menjadi plugin SQLite bawaan Capacitor selama bertahun-tahun dan masih dipelihara (8.1.1 dikirimkan pada Agustus 2026). Alasan orang berpindah adalah spesifik:
- Serialisasi Bridge. Setiap hasil melewati jembatan Capacitor sebagai JSON. Ini baik untuk kueri kecil, dan terasa ketika Anda memuat ribuan baris untuk sinkronisasi atau pencarian.
- SQLCipher selalu termasuk. Plugin tersebut bergantung pada SQLCipher di iOS dan Android bahkan jika Anda tidak pernah mengenkripsi. Ini menambah ukuran native dan berarti biner Anda mengandung enkripsi code yang harus Anda pertimbangkan dalam jawaban export compliance.
- Model penyimpanan web. Pada web, itu menggunakan
jeep-sqliteAnda harus mengingat untuk menyimpan, dan seluruh database hidup di memori.saveToStore()Anda harus mengingat untuk menyimpan, dan seluruh basis data hidup di memori. - Permukaan besar API. Penghubung koneksi, pengecekan konsistensi, koneksi baca-saja dan tidak sesuai, tabel sinkron, import dan ekspor JSON. Kuat, tetapi banyak hal untuk dipelajari untuk "jalankan SQL".
- Satu kata sandi per aplikasi. Enkripsi menggunakan rahasia tunggal yang disimpan oleh plugin (
setEncryptionSecret), yang dibagikan oleh setiap basis data yang dienkripsi di aplikasi.
Pembandingan samping-samping
@capacitor-community/sqlite 8.1 |
@capgo/capacitor-fast-sql 8.2 |
|
|---|---|---|
| Platform | iOS, Android, Web, Electron | iOS, Android, Web |
| Jalur data | Jembatan Capacitor | Situs web HTTP lokal dengan token per-koneksi (native) |
| Mesin web | jeep-sqlite (sql.js + IndexedDB, manual) saveToStore) |
Resmi @sqlite.org/sqlite-wasm Dengan OPFS, tulisan ditulis ke file |
| Enkripsi | SQLCipher selalu dibundel, satu plugin-manajer kata sandi | Pilihan SQLCipher, kunci dilewatkan per database pada connect() |
| Pengelola Paket Swift | Ya (Package.swift) |
Ya (Package.swift) |
| Pengaturan versi skema | upgradeStatements / addUpgradeStatement |
Sendiri, biasanya PRAGMA user_version |
| Import/ekspor JSON, sinkron tabel | Ya | No |
| Database yang sudah diisi dari asset | copyFromAssets() |
Salin file itu sendiri sebelum connect() |
| Pembantu Nilai-Kunci | No | KeyValueStore |
| Bantuan nilai | BLOB | Iya Uint8Array |
| Iya, seperti | TypeORM bawaan capacitor driver |
Driver (Kysely bekerja dengan baik) |
| Setup Lokal Nativ | Salin Web: sql-wasm.wasm |
iOS NSAllowsLocalNetworking, Android Aturan Lokal Cleartext |
| Pengelola | Komunitas Capacitor | Capgo |
Mengapa Tetap di Plugin Komunitas
Praktislah. Tetap jika:
- Anda mengirimkan Elektronik Membangun,
- Anda gunakan TypeORM (driver capacitor-nya ditulis terhadap plugin komunitas, lihat) TypeORM dengan Capacitor),
- Andalkan import / export JSON atau sinkronisasi tabel dan tidak ingin membangunnya lagi,
- Kueri kamu kecil dan aplikasi berjalan dengan baik hari ini.
When Fast SQL lebih baik
Pindah jika:
- Kamu memuat atau menulis dataset besar (sumber daya sinkron, katalog offline, indeks pencarian, log CRDT),
- Kamu ingin enkripsi hanya untuk beberapa database, dengan kunci dari Keychain atau Keystore,
- Andai Anda tidak memerlukan SQLCipher dalam aplikasi.
- Kamu ingin file SQLite yang nyata di web melalui OPFS bukan salinan di memori,
- Kamu ingin API: menghubungkan, menjalankan, menjalankan, transaksi yang sederhana,
Untuk walkthrough lengkap dari Fast SQL itu sendiri, lihat Bagaimana menggunakan SQLite di aplikasi Capacitor.
Langkah 1: instal Fast SQL di samping plugin lama
Tetapkan plugin komunitas terinstal selama satu rilis sehingga Anda dapat memindahkan data yang ada.
bun add @capgo/capacitor-fast-sql
bunx cap sync
Konfigurasi asli Fast SQL memerlukan:
- iOS:
NSAppTransportSecurityiOSNSAllowsLocalNetworking=true>Info.plist. - di: a
network_security_config.xmlyang memungkinkan teks terbuka untuklocalhostdan127.0.0.1, yang diacu dari manifest. - Enkripsi:
net.zetetic:sqlcipher-androiddalam modul aplikasi Android danCapgoCapacitorFastSql/SQLCiphermengenkripsi SQLite di __CAPGO_KEEP_0__ enkripsi SQLite di Capacitor. - Web:
Cross-Origin-Opener-Policy: same-origindanCross-Origin-Embedder-Policy: require-corpLangkah 2: peta __CAPGO_KEEP_0__
Langkah 2: Peta 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();
Setelah:
import { FastSQL } from '@capgo/capacitor-fast-sql';
const db = await FastSQL.connect({ database: 'app', walMode: true, performancePresets: true });
FastSQL.connect() mengembalikan koneksi yang sudah ada jika database sudah dibuka, sehingga tidak ada isConnection / retrieveConnection tarian.
Peta metode
| 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 |
Satu PRAGMA user_version runner migrasi |
copyFromAssets() |
Salin sebuah paket .db into Directory.Data sebelum pertama kali connect() |
setEncryptionSecret() + mode: 'secret' |
encrypted: true, encryptionKey on connect() |
initWebStore() / saveToStore() |
Tidak perlu, OPFS menyimpan penulisan |
Pertanyaan dan Penulisan
Sebelumnya:
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;
Setelahnya:
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 dikunci oleh nama kolom.
Eksekusi statement multi-statement
Masyarakat execute() menerima string dengan beberapa statement yang dipisahkan oleh ;Fast SQL mempersiapkan satu statement per panggilan. Pisahkan SQL Anda, atau lebih baik, 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 pada ; dengan cara yang sederhana split(';') jika statement mana pun mengandung tubuh trigger atau literal string dengan titik koma.
Perbarui statement ke user_version
Plugin masyarakat menyimpan versi schema di PRAGMA user_version Jika Anda menjaga nomor versi yang sama, basis data pengguna yang sudah ada sudah berada di versi yang tepat setelah migrasi file pada 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 versi yang sebenarnya user_version Pada instalasi yang sudah ada sebelumnya sebelum Anda mengandalkan hal ini. Catatnya dari plugin lama di rilis Anda saat ini jika Anda tidak yakin.
Basis data yang sudah diisi
Plugin komunitas’s copyFromAssets() Salinan basis data yang dibundel pada pertama kali menjalankan. Dengan SQL Cepat, letakkan file di mana plugin mencari sebelum terhubung. SQL Cepat menyimpan <name>.db di Documents di iOS dan di direktori aplikasi files directory pada Android, yang keduanya 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 yang besar, download dalam bagian-bagian atau kirim file yang dikompresi dan gunakan plugin file asli untuk menyalin daripada base64 di JavaScript.
Langkah 3: migrasi data pengguna yang sudah ada
Pengguna yang memperbarui aplikasi Anda memiliki basis data yang dibuat oleh plugin komunitas. Basis data ini berada di jalur yang berbeda dengan nama yang berbeda:
| Plugin Komunitas | SQL Cepat | |
|---|---|---|
| iOS | Documents/<name>SQLite.db (default iosDatabaseLocation) |
Documents/<name>.db |
| Andoid | databases/<name>SQLite.db |
files/<name>.db |
Pilihan A: salin file (basis data tidak terenkripsi)
Paling cepat, dan semua tetap: indeks, 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 FastSQL.connect({ database: name }). Catatan:
getUrl()(iOS dan Android) mengembalikan URL file basis data. Mengirimkan URL penuh dengan tidakfile://__CAPGO_KEEP_0__directorybiarkan plugin Filesystem membaca dari jalur apa pun di dalam sandbox Anda.- Menutup koneksi dan memeriksa terlebih dahulu memastikan tidak ada tulisan baru yang tertinggal di sebuah
-walfile. - Tahankan file lama selama satu rilis dan hapusnya nanti dengan koneksi komunitas
delete()Option B: salin baris-baris di JavaScript (database yang terenkripsi, atau perubahan skema)
Option B: salin baris dalam JavaScript (database yang dienkripsi, atau perubahan skema)
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);
}
}
dan 'no-encryption' and false di createConnection jika sumbernya tidak terenkripsi. Plugin komunitas memerlukan iosIsEncryption / androidIsEncryption di capacitor.config Untuk mode yang terenkripsi, Anda sudah memiliki mereka jika Anda telah menggunakan mereka. Untuk tabel besar, navigasikan dengan halaman. WHERE rowid > ? ORDER BY rowid LIMIT 5000.
Kedua plugin menggunakan SQLCipher 4 default, sehingga file yang terenkripsi juga dapat dibuka secara langsung dengan Fast SQL menggunakan kata sandi yang sama. Plugin komunitas mengelola kata sandi tersebut secara internal, dan penggandaan baris menghindari ketergantungan pada detail tersebut.
Langkah 4: hapus plugin lama
Setelah satu atau dua rilis dengan migrasi yang berlaku:
bun remove @capacitor-community/sqlite jeep-sqlite
bunx cap sync
Hapus sql-wasm.wasm dari aset dan setiap jeep-sqlite konfigurasi di main.ts Menghapus plugin juga menghapus ketergantungannya pada SQLCipher, sehingga jika Anda tidak memilih untuk menggunakan enkripsi Fast SQL, maka file biner iOS dan Android menjadi lebih kecil.
Pemigrasian code adalah JavaScript, sehingga dapat dikirimkan bersama dengan Capgo pembaruan hidupTapi rilis yang menambahkan Fast SQL adalah perubahan asli dan memerlukan pembangunan toko. Kirimkan pembangunan asli terlebih dahulu. Capgo Bangun Jika Anda tidak memiliki Mac di sekitar, Anda bisa membuatnya di cloud jika Anda tidak memiliki Mac di sekitar (App Store harus mengupload Xcode 26 atau lebih baru sejak April 2026).
Penyelesaian Masalah
Fast SQL terhubung tetapi setiap kueri gagal di iOS. NSAllowsLocalNetworking Komponen ini hilang dari aplikasi Anda Info.plistatau aplikasi Anda tidak direkonstruksi setelah menambahkannya.
Android: CLEARTEXT communication to localhost not permitted. Tambahkan alamat localhost domain-config ke konfigurasi keamanan jaringan Anda. Jika Anda sudah memiliki satu untuk SSL pinning, gabungkan mereka.
Hanya bagian dari schema saya yang dibuat. Anda melewati string multi-statement ke execute()Splitkannya menjadi array.
INSERT ... RETURNING mengembalikan tidak ada di Android. In Fast SQL 8.2, Android hanya menampilkan baris untuk statement yang dimulai dengan SELECT, PRAGMA atau EXPLAIN. Gunakan insertId dari run().
Booleans tidak cocok pada bacaan Android. Gunakan 1/0 bukan true/false dalam parameter kueri. Android mengikat parameter kueri baca sebagai teks.
Database yang dicopy kosong. Plugin komunitas telah dikonfigurasi dengan custom iosDatabaseLocation, atau nama sumber berbeda. Log URL yang dikembalikan oleh getUrl().
Data web dari plugin lama hilang. Komunitas plugin menyimpan data web di IndexedDB melalui jeep-sqlite, Fast SQL menggunakan OPFS. Re-sync klien web dari backend Anda, atau ekspor dengan plugin lama's exportToJson dan impor baris ke Fast SQL.
Opsi lainnya
@capgo/capacitor-data-storage-sqlitejika yang Anda sebenarnya butuhkan adalah penyimpanan kunci-nilai string yang didukung oleh SQLite. Lihat penyimpanan kunci-nilai di Capacitor.- Suatu ORM atau pembuat kueri di atas: Kysely berfungsi dengan Fast SQL melalui driver khusus singkat. Drizzle saat ini lebih cocok dengan plugin komunitas.
Fast SQL API yang lengkap ada di plugin dokumen dan di halaman plugin.