Untuk penyimpanan kunci-nilai di Capacitor, gunakan @capacitor/preferences untuk beberapa pengaturan kecil, penyimpanan kunci-nilai SQLite yang didukung untuk apa pun yang lebih besar atau lebih banyak, dan Keychain atau Keystore untuk rahasia. Panduan ini membandingkan opsi yang tersedia di Capacitor 8, menampilkan contoh kerja code untuk setiap opsi, dan menjelaskan cara beralih dari satu ke opsi lainnya tanpa kehilangan data pengguna.
Banyak aplikasi akhirnya menggunakan dua di antara mereka secara bersamaan: Preferensi atau SQLite untuk keadaan aplikasi, dan penyimpanan aman untuk token autentikasi.
Ringkasan pilihan
localStorage / IndexedDB |
@capacitor/preferences |
Fast SQL KeyValueStore |
@capgo/capacitor-data-storage-sqlite |
@capgo/capacitor-native-biometric setData |
|
|---|---|---|---|---|---|
| Ditopang oleh | Penyimpanan WebView | Pengaturan Nilai Pengguna | File SQLite | File SQLite | Penyimpanan Kunci |
| Tahan terhadap pembaruan penyimpanan OS | Tidak dijamin | Iya | Ya | Ya | Ya |
| Jenis nilai | Nilai string (localStorage) | Nilai string | Nilai JSON, bilangan, boolean, Uint8Array |
Nilai string | Nilai string |
| Rentang ukuran yang baik | Kecil | Kecil, beberapa KB per nilai | Nilai besar besar, banyak kunci | Banyak kunci | Terlalu kecil (di bawah ~8 KB pada Android) |
| Enkripsi | Tidak | Tidak | Opsional SQLCipher, kunci dari penyimpanan yang aman | Opsional SQLCipher, sandi dalam konfigurasi | Ya, didukung oleh perangkat keras |
| Nama Ruang | Per asal | group Pilihan |
store pilihan |
Tabel | Nama kunci |
| Cari dengan awalan | Tidak | Tidak | Tampilkan kunci | filtervalues |
Tidak |
| Web | Iya | localStorage |
SQLite Wasm (OPFS) | IndexedDB | Not untuk rahasia |
Mengapa tidak menggunakan localStorage
localStorage and IndexedDB work inside a Capacitor WebView, but the data belongs to the WebView, not to your app’s native storage. The OS can reclaim WebView storage when the device runs low on space, and Capacitor’s own documentation recommends against relying on it for data you cannot lose. Changing the app’s hostname or scheme in capacitor.config juga mengubah asal, yang menunjuk WebView ke penyimpanan kosong yang berbeda.
Pakai mereka sebagai cache yang dapat menghilang. Gunakan salah satu pilihan yang didukung oleh penyimpanan asli untuk semua yang lain.
Option 1: Capacitor Preferensi untuk pengaturan ringan
@capacitor/preferences adalah plugin resmi untuk data nilai kunci ringan. Pada iOS, menulis ke UserDefaultspada Android ke SharedPreferencespada web ke localStorage.
bun add @capacitor/preferences
bunx cap sync
import { Preferences } from '@capacitor/preferences';
interface Settings {
theme: 'light' | 'dark' | 'system';
fontScale: number;
}
const DEFAULTS: Settings = { theme: 'system', fontScale: 1 };
export async function loadSettings(): Promise<Settings> {
const { value } = await Preferences.get({ key: 'settings' });
return value ? { ...DEFAULTS, ...JSON.parse(value) } : DEFAULTS;
}
export async function saveSettings(settings: Settings): Promise<void> {
await Preferences.set({ key: 'settings', value: JSON.stringify(settings) });
}
Pakai untuk: tema, bahasa, flag onboarding, tab terakhir yang dipilih, toggle fitur.
Tidak pakai untuk: Rahasia.
- Secrets. Nilai disimpan dalam teks biasa di dalam sandbox aplikasi, dan termasuk dalam cadangan perangkat.
- Nilai besar.
UserDefaultsdanSharedPreferencesmengisi seluruh file mereka ke dalam memori. Blok JSON besar memperlambat setiap baca dan tulis. - Banyak kunci yang perlu Anda daftar atau hapus dengan awalan.
keys()mengembalikan semuanya, sehingga Anda dapat menyaring di JavaScript.
Preferences.configure({ group: 'MyApp' }) mengubah nama ruang kunci yang disimpan di bawahnya. Kelompok default adalah CapacitorStorage.
Pilihan 2: penyimpanan kunci-nilai SQLite
Setelah Anda menyimpan respons API yang dicadangkan, draft, antrian offline, atau ratusan entri, file SQLite adalah rumah yang lebih baik. Ini mengatasi nilai besar, tulisan atomik, dan Anda dapat mengenkripsinya.
Penyimpanan Kunci-Nilai SQL Cepat
@capgo/capacitor-fast-sql termasuk KeyValueStore kelas di atas koneksi SQLite-nya. Ini menciptakan __kv_store mengatur jenis nilai, dan mendukung beberapa penyimpanan bernama dalam satu database.
bun add @capgo/capacitor-fast-sql
bunx cap sync
Fast SQL memerlukan dua pengaturan asli (jaringan lokal iOS di Info.plist, aturan localhost jelas pada Android). Mereka dibahas dalam Cara Menggunakan SQLite di Aplikasi Capacitor.
import { KeyValueStore } from '@capgo/capacitor-fast-sql';
const cache = await KeyValueStore.open({ database: 'app', store: 'api-cache' });
// Objects, arrays, numbers, booleans, null and Uint8Array are stored as-is
await cache.set('user:42', { id: 42, name: 'Ada', roles: ['admin'] });
await cache.set('lastSync', Date.now());
const user = (await cache.get('user:42')) as { id: number; name: string } | null;
const exists = await cache.has('lastSync');
const allKeys = await cache.keys();
await cache.remove('user:42');
await cache.clear(); // only clears the 'api-cache' store
await cache.close();
Ringkasan API: open(options), fromConnection(connection, store), set, get (mengembalikan null ketika hilang), has, remove, clear, keys, close.
Beberapa pola yang perlu diketahui:
Beberapa penyimpanan, satu database. Opsi store menggunakan namespace kunci, sehingga settings, drafts dan (And) api-cache bisa hidup berdampingan dan dihapus secara independen.
Kunci-nilai di samping tabel nyata. Jika aplikasi Anda sudah menggunakan Fast SQL untuk data relasional, gunakan koneksi yang sama lagi daripada membuka koneksi kedua:
import { FastSQL, KeyValueStore } from '@capgo/capacitor-fast-sql';
const db = await FastSQL.connect({ database: 'app' });
const drafts = await KeyValueStore.fromConnection(db, 'drafts');
// You own `db`: drafts.close() does not disconnect it
Di kemudian hari, ketika blob kunci-nilai tumbuh menjadi sesuatu yang ingin Anda cari (contoh: semua draft yang lebih tua dari seminggu), Anda bisa memindahkannya ke tabel yang tepat di database yang sama.
Penyimpanan kunci-nilai yang dienkripsi
KeyValueStore.open menerima opsi yang sama seperti FastSQL.connecttermasuk encrypted dan encryptionKey di iOS dan Android:
import { KeyValueStore } from '@capgo/capacitor-fast-sql';
import { NativeBiometric } from '@capgo/capacitor-native-biometric';
async function getKey(): Promise<string> {
const { isSaved } = await NativeBiometric.isDataSaved({ key: 'kv.key' });
if (isSaved) return (await NativeBiometric.getData({ key: 'kv.key' })).value;
const bytes = crypto.getRandomValues(new Uint8Array(32));
const key = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
await NativeBiometric.setData({ key: 'kv.key', value: key });
return key;
}
const secureStore = await KeyValueStore.open({
database: 'secure-kv',
encrypted: true,
encryptionKey: await getKey(),
});
Ini memerlukan SQLCipher pada bangun native. Konfigurasi, serta apa yang harus dilakukan ketika kunci hilang setelah restorasi backup, dapat ditemukan di Cara mengenkripsi basis data SQLite di Capacitor.
@capgo/capacitor-data-storage-sqlite
@capgo/capacitor-data-storage-sqlite is sebuah plugin kunci-nilai yang khusus untuk SQLite (dahulu oleh Jean Pierre Quéau, sekarang dipelihara oleh Capgo). Nilai-nilai adalah string, dan itu menambahkan beberapa fitur tambahan: beberapa tabel per toko, penyaringan awalan dan akhir, dan import dan export JSON.
bun add @capgo/capacitor-data-storage-sqlite
bunx cap sync
import { CapgoCapacitorDataStorageSqlite as Store } from '@capgo/capacitor-data-storage-sqlite';
await Store.openStore({ database: 'appStore', table: 'settings' });
await Store.set({ key: 'locale', value: 'fr' });
await Store.set({ key: 'profile', value: JSON.stringify({ name: 'Ada' }) });
const { value } = await Store.get({ key: 'locale' });
const { result: hasProfile } = await Store.iskey({ key: 'profile' });
const { keys } = await Store.keys();
// Switch table inside the same store
await Store.setTable({ table: 'drafts' });
const { values } = await Store.filtervalues({ filter: 'note%' }); // values whose key starts with "note"
await Store.remove({ key: 'note-1' });
await Store.clear(); // clears the current table
filtervalues menerapkan penyaringan sebagai SQL LIKE polanya pada kunci (note% untuk awalan, %note untuk akhir, teks biasa untuk mengandung). Pola tersebut dimasukkan ke dalam string SQL, jadi hanya lewatkan penyaringan yang Anda kendalikan, tidak pernah input pengguna mentah.
Pada web itu menggunakan IndexedDB melalui localforageyang Anda instal secara terpisah:
bun add localforage
Tentang enkripsinya: openStore({ encrypted: true, mode: 'secret' }) menggunakan SQLCipher dengan kata sandi dari capacitor.config bawah plugins.CapgoCapacitorDataStorageSqlite.encryptionSecretKata sandi tersebut dikirimkan bersama dengan bundle aplikasi Anda, dan jika Anda tidak menyetelnya plugin tersebut akan kembali ke default bawaan. Tidaklah aman untuk menyimpan rahasia yang penting menggunakan metode ini. Gunakan kunci dari Keychain atau Keystore, seperti dalam contoh Fast SQL di atas.
Fast SQL KeyValueStore atau data-storage-sqlite?
- Pilih Fast SQL
KeyValueStoreJika Anda ingin nilai yang tipe dan tidak perlu JSON manual, nilai biner, kunci enkripsi waktu eksekusi, atau sudah menggunakan Fast SQL untuk tabel. - Pilih data-storage-sqlite Jika Anda membutuhkan fitur tabel dan filter, ekspor dan impor JSON, atau dukungan Electron.
Pilihan 3: Keychain dan Keystore untuk rahasia
Token autentikasi, token refresh, kunci API dan kunci enkripsi database masuk ke penyimpanan aman platform. @capgo/capacitor-native-biometric (8.6.0 dan lebih lanjut) mengungkapkan kunci nilai yang umum API di atas Keychain iOS dan Keystore Android:
bun add @capgo/capacitor-native-biometric
bunx cap sync
import { AccessControl, NativeBiometric } from '@capgo/capacitor-native-biometric';
// Silent read and write
await NativeBiometric.setData({ key: 'session.refreshToken', value: token });
const { value: refreshToken } = await NativeBiometric.getData({ key: 'session.refreshToken' });
// Require Face ID / Touch ID / fingerprint to read
await NativeBiometric.setData({
key: 'wallet.pin',
value: pin,
accessControl: AccessControl.BIOMETRY_ANY,
});
const { value: secretPin } = await NativeBiometric.getSecureData({
key: 'wallet.pin',
reason: 'Confirm it is you',
});
await NativeBiometric.deleteData({ key: 'session.refreshToken' });
Pertahankan nilai kecil. Dokumen plugin menyatakan bahwa enkripsi Keystore Android bekerja dengan baik di bawah sekitar 8 KB per nilai. Jika Anda membutuhkan melindungi banyak data, simpan satu kunci acak di sini dan gunakan untuk mengenkripsi database SQLite. Artikel kami tentang penyimpanan aman untuk token offline menggali lebih dalam tentang pengelolaan token.
Ingatlah bahwa item Keychain di iOS dapat bertahan lebih lama dari penghapusan aplikasi. Pada pertama kali menjalankan setelah instalasi segar, hapus rahasia yang kering jika aplikasi Anda mengharapkan permukaan yang bersih (simpan flag 'sudah dilakukan pertama kali' di Preferensi, yang dihapus pada penghapusan, dan hapus entri Keychain ketika itu hilang).
Pemilihan: daftar keputusan
- Apakah itu rahasia? Token, kata sandi, PIN, kunci. Gunakan penyimpanan Keychain atau Keystore.
- Apakah itu beberapa pengaturan kecil? Gunakan Preferensi.
- Apakah itu beberapa entri, JSON besar, data biner, atau cache yang ingin Anda hapus dan kelompokkan? Gunakan penyimpanan key-value SQLite.
- Do you need to filter, sort or join it? Tidak lagi data key-value. Buatlah tabel, lihat panduan SQLite Petunjuk SQLiteatau gunakan layer yang ditipekan seperti Kysely.
Migrasikan data yang sudah ada antara penyimpanan
Pindah dari localStorage atau Preferensi ke penyimpanan SQLite adalah salinan sekali saja pada startup. Lakukan sebelum aplikasi lain membaca data, dan catat bahwa itu sudah berjalan.
import { Preferences } from '@capacitor/preferences';
import { KeyValueStore, type KeyValueValue } from '@capgo/capacitor-fast-sql';
export async function migrateToSqliteStore(): Promise<KeyValueStore> {
const kv = await KeyValueStore.open({ database: 'app', store: 'settings' });
if (await kv.has('__migrated_v1')) return kv;
const { keys } = await Preferences.keys();
for (const key of keys) {
const { value } = await Preferences.get({ key });
if (value === null) continue;
let parsed: KeyValueValue = value;
try {
parsed = JSON.parse(value) as KeyValueValue;
} catch {
// keep plain strings as strings
}
await kv.set(key, parsed);
}
// Also copy from localStorage if older versions used it
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key && !(await kv.has(key))) {
await kv.set(key, localStorage.getItem(key));
}
}
await kv.set('__migrated_v1', true);
// Remove the old copies only after a release or two, once you are confident
return kv;
}
Hapus rahasia dari penyimpanan lama segera setelah mereka dicopy ke penyimpanan yang lebih aman. Tinggalkan token di Preferensi setelah memindahkannya ke Keychain tetap menjaga eksposur asli.
Karena ini code berjalan di JavaScript, Anda dapat mengirimkannya dengan Capgo live updateRilis SQLite plugin itu sendiri adalah native, jadi rilis yang menambahkannya membutuhkan build penyimpanan. Kirim plugin terlebih dahulu, kemudian migrasi code.
Troubleshooting
Nilai Preferensi null setelah pembaruan di web. Perubahan asal (port, hostname, atau scheme), sehingga localStorage is sebuah penyimpanan kosong yang berbeda.
SQL Cepat KeyValueStore.open mengeluarkan kesalahan pada iOS. Saluran HTTP lokal diblokir. Tambahkan NSAllowsLocalNetworking ke Info.plist rebuild aplikasi native.
get mengembalikan string di mana Anda mengharapkan objek di penyimpanan data-sqlite. dan bangun kembali aplikasi asli. JSON.parse Nilainya.
Rahasia hilang setelah mengembalikan cadangan pada ponsel baru. Keystore keys and device-only Keychain items do not transfer to new hardware. Treat secure storage as a cache of credentials you can re-obtain by signing in again.
Rahasia hilang setelah mengembalikan cadangan di ponsel baru. Diharapkan: Preferensi dihapus bersama aplikasi, tetapi item Keychain dapat tetap ada. Gunakan pola flag pertama kali di atas.
Ringkasan
- Preferensi: pengaturan kecil, tidak sensitif.
- Penyimpanan nilai SQLite (SQL Cepat)
KeyValueStoreatau@capgo/capacitor-data-storage-sqliteBanyak nilai atau nilai besar, cache, draft, dengan kemampuan enkripsi opsional. - Penyimpanan Nilai Kunci
@capgo/capacitor-native-biometricsetDataPenyimpanan nilai SQLite (SQL Cepat)
Referensi Plugin: Penyimpanan nilai SQLite (SQL Cepat), Penyimpanan Data SQLitedan plugin biometrik native halaman.