Per il storage dei valori chiave in Capacitor, utilizza @capacitor/preferences for a handful of small settings, a SQLite-backed key-value store for anything larger or more numerous, and the Keychain or Keystore for secrets. This guide compares the options available on Capacitor 8, shows working code for each, and explains how to move from one to another without losing user data.
La maggior parte degli app utilizza due di questi contemporaneamente: le Preferenze o SQLite per lo stato dell'app e il storage sicuro per il token di autenticazione.
Le opzioni in un colpo d'occhio
localStorage / IndexedDB |
@capacitor/preferences |
SQL veloce KeyValueStore |
@capgo/capacitor-data-storage-sqlite |
@capgo/capacitor-native-biometric setData |
|
|---|---|---|---|---|---|
| Sostenuto da | Memoria del WebView | UserDefaults / SharedPreferences | File SQLite | File SQLite | Cassetto delle chiavi / Archivio delle chiavi |
| Sopravvive alla pulizia dello storage del sistema | Non garantito | Sì | Sì | Sì | Sì |
| Tipi di valore | Stringhe (localStorage) | Stringhe | Valori JSON, numeri, booleani, Uint8Array |
Stringhe | Stringhe |
| Buona fascia di dimensioni | Piccolo | Piccolo, alcuni KB per valore | Valori grandi, molte chiavi | Molte chiavi | Estremamente piccoli (sotto ~8 KB su Android) |
| Crittografia | No | No | SQLCipher facoltativo, chiave da archivio sicuro | SQLCipher facoltativo, passphrase nella configurazione | Sì, supportato da hardware |
| Namespace | Per origine | group opzione |
store opzione |
Tabelle | Nomina chiavi |
| Cerca per prefisso | No | No | Elenco chiavi | filtervalues |
No |
| Web | Sì | localStorage |
SQLite Wasm (OPFS) | IndexedDB | Noti per segreti |
Perché non 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 modifica anche l'origine, che punta il WebView a uno storage diverso e vuoto.
Usali come cache che possono scomparire. Utilizza una delle opzioni native per tutto il resto.
Opzione 1: Capacitor Preferenze per impostazioni leggere
@capacitor/preferences è il plugin ufficiale per dati di valore leggeri. Su iOS scrive su UserDefaultssu Android su SharedPreferencese su web su 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) });
}
Utilizzalo per: tema, lingua, flag di onboarding, ultima scheda selezionata, toggle di feature.
Non utilizzalo per: Segreti.
- Secrets. Valori sono memorizzati in testo puro all'interno del sandbox dell'app, e sono inclusi nei backup del dispositivo.
- Valori grandi.
UserDefaultseSharedPreferencescaricano l'intero file in memoria. I grandi blocchi JSON rallentano ogni lettura e scrittura. - molte chiavi che devi elencare o cancellare per prefisso.
keys()ritorna tutto, quindi filtri in JavaScript.
Preferences.configure({ group: 'MyApp' }) cambia lo spazio dei nomi in cui sono memorizzate le chiavi. Il gruppo predefinito è CapacitorStorage.
Opzione 2: un archivio chiavi-valori SQLite
Una volta memorizzate le risposte cache API, i bozzetti, le code offline o centinaia di voci, un file SQLite è un miglior rifugio. Gestisce valori grandi, le scritture sono atomiche e puoi criptarlo.
SQL KeyValueStore veloce
@capgo/capacitor-fast-sql include un KeyValueStore class sopra la sua connessione SQLite. Crea un __kv_store tabella, mantiene il tipo di valore e supporta più archivi denominati in un unico database.
bun add @capgo/capacitor-fast-sql
bunx cap sync
Fast SQL ha bisogno di due impostazioni native (rete locale iOS in Info.plist, una regola di testo chiaro su localhost per Android). Sono coperte in Come utilizzare SQLite in un'app 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();
Riepilogo API: open(options), fromConnection(connection, store), set, get (restituisce null quando mancante), has, remove, clear, keys, close.
Due modelli da conoscere:
Più archivi, un unico database. La store opzioni namespace chiavi, quindi settings, drafts e api-cache possono vivere fianco a fianco e essere eliminati independentemente.
Valori chiave accanto a vere tabelle. Se il tuo app già utilizza Fast SQL per dati relazionali, riutilizza la connessione al posto di aprire una seconda:
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
Più tardi, quando un blob di valori chiave cresce in qualcosa che vuoi interrogare (ad esempio tutti i bozzetti più vecchi di una settimana), puoi spostarlo in una vera tabella nello stesso database.
Memoria di archiviazione chiave-valore crittografata
KeyValueStore.open accetta le stesse opzioni come FastSQL.connect, inclusi encrypted e encryptionKey su iOS e 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(),
});
Questo richiede SQLCipher nelle costruzioni native. La configurazione, più ciò che fare quando la chiave è persa dopo il ripristino di un backup, è in Come criptare un database SQLite in Capacitor.
@capgo/capacitor-data-storage-sqlite
@capgo/capacitor-data-storage-sqlite è un plugin di archiviazione chiave-valore dedicato su SQLite (originariamente di Jean Pierre Quéau, ora mantenuto da Capgo). I valori sono stringhe, e aggiunge alcune funzionalità aggiuntive: più tabelle per archivio, filtro per prefisso e suffisso, importazione e esportazione 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 applica il filtro come un SQL LIKE pattern sul chiave (note% per un prefisso, %note per un suffisso, testo normale per contiene). Il pattern viene inserito nella stringa SQL, quindi passa solo filtri che controlli, mai input utente crudo.
Sul web utilizza IndexedDB attraverso localforageche installi separatamente:
bun add localforage
Sulla sua crittografia: openStore({ encrypted: true, mode: 'secret' }) utilizza SQLCipher con una passphrase da capacitor.config sotto plugins.CapgoCapacitorDataStorageSqlite.encryptionSecretQuella passphrase viene inviata all'interno del tuo bundle di app, e se non la imposti il plugin ricade su un default predefinito. Trattalo come protezione contro l'ispezione di file casuale, non contro qualcuno che scompatta il tuo app. Per segreti reali utilizza una chiave dalla Keychain o Keystore, come nell'esempio di Fast SQL sopra.
Fast SQL KeyValueStore o data-storage-sqlite?
- Seleziona SQL veloce
KeyValueStorese desideri valori tipizzati senza JSON manuale, valori binari, una chiave di crittografia runtime o già utilizzi SQL veloce per le tabelle. - Seleziona dati-storage-sqlite se hai bisogno delle sue funzionalità di tabella e filtro, l'esportazione e l'importazione di JSON o il supporto per Electron.
Opzione 3: Keychain e Keystore per segreti
I tokeni di autenticazione, i token di refresh, le chiavi API e le chiavi di crittografia del database vanno nel storage sicuro della piattaforma. @capgo/capacitor-native-biometric (8.6.0 e successive) esporre una chiave-valore generica API sopra la Keychain iOS e 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' });
Conserva i valori piccoli. Il plugin documenta che la crittografia basata sul Keystore Android funziona meglio sotto circa 8 KB per valore. Se hai bisogno di proteggere molto dati, memorizza una chiave casuale qui e utilizzala per crittografare un database SQLite. Il nostro post sul storage sicuro per token offline va più a fondo nella gestione dei token.
Ricorda che gli elementi di Keychain su iOS possono sopravvivere all'eliminazione dell'app. Al primo avvio dopo un'installazione fresca, cancella i segreti obsoleti se la tua app si aspetta uno schermo pulito (memorizza un 'flag di prima esecuzione effettuata' nelle Preferenze, che viene eliminato all'eliminazione dell'app, e cancella gli elementi di Keychain quando manca).
Scegliere: una lista di decisioni
- È un segreto? Token, password, PIN, chiave. Utilizza la memorizzazione di Keychain o Keystore.
- È un paio di piccole impostazioni? Utilizza le Preferenze.
- È un po' di dati, grandi JSON, dati binari o cache che desideri scadere e cancellare in gruppi? Utilizza una chiave-valoristica SQLite.
- Hai bisogno di filtrare, ordinare o unire? Non è più dati chiave-valoristica. Crea una tabella, vedi il guida SQLite, o utilizza un layer tipizzato come Kysely.
Migrare i dati esistenti tra i magazzini
Passare da localStorage o Preferenze a un magazzino SQLite è una copia unica all'avvio. Faccialo prima che il resto dell'app legga i dati, e registrate che è stato eseguito.
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;
}
Eliminare i segreti dal vecchio magazzino non appena sono copiati in un archivio sicuro. Lasciare un token in Preferenze dopo averlo spostato nella Keychain mantiene l'esposizione originale.
Poiché questo code esegue in JavaScript, puoi distribuirlo con un Capgo live updateIl plugin SQLite stesso è nativo, quindi la versione che lo aggiunge richiede un build del magazzino. Distribuisci il plugin per primo, poi il code di migrazione.
Risolvere i problemi
Valori delle impostazioni null I valori delle Preferenze sono L'origine è cambiata (port, hostname o schema), quindi localStorage è un magazzino diverso e vuoto.
SQL veloce KeyValueStore.open lancia un errore su iOS. Il canale HTTP locale è bloccato. Aggiungi NSAllowsLocalNetworking to Info.plist Riavvia l'app nativa.
get ritorna una stringa dove si aspettava un oggetto in data-storage-sqlite. Quel plugin memorizza solo stringhe. JSON.parse il valore.
Segreti mancanti dopo il ripristino di un backup su un nuovo telefono. 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.
Impostazioni perse dopo reinstallazione ma token ancora presenti su iOS. Preferenze: si eliminano con l'app, gli elementi della Keychain possono rimanere. Utilizzare il modello di flag di prima esecuzione sopra.
Riassunto
- Preferenze: impostazioni piccole e non sensibili.
- Database di chiave-valore SQLite (SQL veloce)
KeyValueStoreo@capgo/capacitor-data-storage-sqlitemolti o grandi valori, cache, bozzetti, eventualmente crittati. - Chiave di sistema
@capgo/capacitor-native-biometricsetDataSegreti e chiavi di crittografia.
Riferimenti plugin: Risorse SQL veloci, dati-storage-sqlite documentazionee e il pagina plugin di rilevamento biometrico nativo.