MMKV היא ספריית אחסון Key-Value עבור React Native שפיתחה Tencent, החושפת ממשק סינכרוני מבוסס JSI ומציעה ביצועים מהירים פי 25 עד 30 מ-AsyncStorage. בניגוד ל-AsyncStorage שעובד עם Promises ועובר דרך ה-Bridge הישן, react-native-mmkv ניגש לזיכרון ישירות מ-JavaScript, תומך בהצפנה מובנית ב-AES-256, מתאים ל-New Architecture (Bridgeless), ולכן הפך לבחירת ברירת המחדל לאחסון מקומי באפליקציות React Native ב-2026.
react-native-mmkv 3.x מבוסס על JSI ו-Nitro Modules, ועובד באופן סינכרוני ללא Promises וללא חסימה של ה-UI thread.
ביצועי קריאה וכתיבה מהירים פי 25 עד 30 מ-AsyncStorage בבדיקות הרשמיות של Tencent ושל מארק רוסבי.
תמיכה מלאה ב-Hermes, ב-New Architecture (Fabric + TurboModules), וב-Expo Dev Client החל מ-SDK 51.
הצפנה מובנית ב-AES-256 ברמת ה-MMKV instance, ללא תלות ב-Keychain חיצוני.
אינטגרציה ישירה עם Zustand persist, TanStack Query persister ו-Redux Toolkit redux-persist.
הגירה מ-AsyncStorage היא חד-פעמית: סקריפט פשוט מעתיק את כל המפתחות פעם אחת בעת ההפעלה.
מה זה MMKV ולמה הוא קיים
אז קודם כל, מה זה בכלל MMKV? זה מנוע אחסון מבוסס mmap (memory-mapped files) שפיתחה Tencent עבור WeChat, אפליקציה שמשרתת מעל מיליארד משתמשים פעילים. המנוע הליבתי של MMKV כתוב ב-C++ ועושה שימוש ב-protocol buffers לסריאליזציה ובכתיבה Append-Only כדי לצמצם פעולות I/O. ה-wrapper ל-React Native, react-native-mmkv של Marc Rousavy, חושף את ה-API ל-JavaScript דרך JSI (JavaScript Interface). זה אומר שהפונקציות פועלות באופן סינכרוני ובלי מעבר דרך ה-Bridge האסינכרוני הישן.
למה זה חשוב? AsyncStorage נשען על תקשורת Bridge בין JS ל-Native, וכל קריאה דורשת serialize של המחרוזות ועיגון ל-Promise. בנוסף, AsyncStorage שומר הכל כ-string ומשתמש ב-SQLite מתחת לפני השטח. כשמדובר באחסון של flags, JWT tokens, או cache של תשובות API, הזמנים פשוט מצטברים. עם MMKV, קריאה היא קריאה ישירה לזיכרון: storage.getString('token') מחזירה את הערך מיד, בלי await.
חשוב להבין מתי לא להשתמש ב-MMKV: לא מומלץ לאחסן בו אובייקטים גדולים מ-10MB (למשל תמונות בפורמט base64), ולא לאחסן בו מידע שדורש שאילתות (אז עדיף WatermelonDB או Drizzle עם SQLite). בפרויקט האחרון שלי, אגב, חזרנו ל-SQLite אחרי שניסינו לדחוף 80MB של cache תמונות ל-MMKV. זו לא הייתה החלטה חכמה.
MMKV מול AsyncStorage: השוואה מלאה
השוואה ישירה בין שתי הספריות מבהירה למה רוב הצוותים עוברים ל-MMKV. הטבלה הבאה מסכמת את ההבדלים העיקריים נכון ל-2026 (react-native-mmkv 3.x מול @react-native-async-storage/async-storage 2.x):
תכונה
react-native-mmkv 3.x
AsyncStorage 2.x
API
סינכרוני (JSI)
אסינכרוני (Promises)
מהירות קריאה
~0.02ms לערך
~0.5 עד 1ms לערך
מהירות כתיבה
~0.05ms לערך
~1 עד 3ms לערך
טיפוסי נתונים נתמכים
string, number, boolean, Uint8Array
string בלבד (JSON.stringify ידני)
הצפנה מובנית
AES-256 (ברמת instance)
אין (דרוש Keychain חיצוני)
מנוע
mmap + Protocol Buffers
SQLite (אנדרואיד), NSUserDefaults/files (iOS)
New Architecture
תמיכה מלאה (Nitro Modules)
נתמך אך עדיין Bridge-based
תאימות Expo Go
לא (דורש Dev Client)
כן
גודל מומלץ למפתח
עד 10MB
עד 6MB באנדרואיד
איך מתקינים react-native-mmkv ב-Expo?
ב-React Native CLI ההתקנה היא פקודה אחת. ב-Expo נדרש Dev Client כי MMKV מכיל קוד נייטיב שלא מגיע עם Expo Go.
התקנה ב-React Native CLI
npm install react-native-mmkv
cd ios && pod install && cd ..
npx react-native run-ios
npx react-native run-android
אם אתם משתמשים ב-EAS Build, פשוט הריצו eas build --profile development --platform all כדי לקבל Dev Client עם MMKV מובנה. אין צורך בקונפיגורציה נוספת ב-app.json, הספרייה מתגלית אוטומטית על ידי Expo autolinking.
שימוש בסיסי וטיפוסי נתונים
היופי של MMKV הוא ה-API הנקי. צרו instance פעם אחת ברמת המודול והשתמשו בו בכל מקום:
// storage.ts
import { MMKV } from 'react-native-mmkv';
export const storage = new MMKV({
id: 'app-storage',
});
// הגדרת ערכים, סינכרוני, ללא await
storage.set('user.token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6...');
storage.set('user.id', 42);
storage.set('user.onboarded', true);
// קריאה, מחזיר את הערך מיד
const token = storage.getString('user.token'); // string | undefined
const userId = storage.getNumber('user.id'); // number | undefined
const onboarded = storage.getBoolean('user.onboarded'); // boolean | undefined
// בדיקת קיום ומחיקה
if (storage.contains('user.token')) {
storage.delete('user.token');
}
// קבלת כל המפתחות
const allKeys = storage.getAllKeys();
// ניקוי מלא
storage.clearAll();
לאובייקטים מורכבים, השתמשו ב-JSON.stringify כרגיל, אבל הזכרו שהקריאה עדיין מהירה כי אין latency של Bridge:
type UserPrefs = { theme: 'dark' | 'light'; locale: string };
export function savePrefs(prefs: UserPrefs) {
storage.set('prefs', JSON.stringify(prefs));
}
export function loadPrefs(): UserPrefs | null {
const raw = storage.getString('prefs');
return raw ? (JSON.parse(raw) as UserPrefs) : null;
}
האזנה לשינויים עם useMMKVString
הספרייה כוללת hooks ל-React שמרכיבים מחדש את הקומפוננטה כשהערך משתנה. שימושי במיוחד להגדרות משתמש:
אחד היתרונות הגדולים של MMKV הוא הצפנה ברמת ה-instance, ללא תלות בספרייה חיצונית כמו react-native-keychain. כל מה שצריך הוא להעביר encryptionKey ביצירת ה-instance:
אפשר ליצור כמה instances מקבילים, לדוגמה אחד לכל user בסביבת multi-account, או חלוקה לפי domain (auth, settings, cache). כל instance הוא קובץ mmap נפרד על המכשיר, מה שמאפשר מחיקה סלקטיבית של נתוני משתמש בלי לפגוע בהגדרות כלליות.
איך עוברים מ-AsyncStorage ל-MMKV?
הגירה מ-AsyncStorage היא פעולה חד-פעמית בעת ה-bootstrap של האפליקציה. הסקריפט הבא קורא את כל המפתחות מ-AsyncStorage, כותב אותם ל-MMKV, ואז מנקה את AsyncStorage:
import AsyncStorage from '@react-native-async-storage/async-storage';
import { MMKV } from 'react-native-mmkv';
const storage = new MMKV({ id: 'app-storage' });
const MIGRATION_KEY = 'mmkv.migration.v1.done';
export async function migrateFromAsyncStorage() {
if (storage.getBoolean(MIGRATION_KEY)) return;
const keys = await AsyncStorage.getAllKeys();
const pairs = await AsyncStorage.multiGet(keys);
for (const [key, value] of pairs) {
if (value !== null) storage.set(key, value);
}
await AsyncStorage.multiRemove(keys);
storage.set(MIGRATION_KEY, true);
}
קראו ל-migrateFromAsyncStorage() פעם אחת ב-App.tsx לפני שאתם מציגים את ה-Splash. שימו לב: ה-flag MIGRATION_KEY מאוחסן ב-MMKV עצמו, כך שגם אם המשתמש יסיר את האפליקציה ויתקין מחדש, לא יהיה ניסיון הגירה כפול.
היתרון הכי משמעותי כאן: rehydration קורה סינכרונית בעת אתחול האפליקציה. אין הבהוב של מסך לא מאומת לפני שה-token עולה (תרחיש מוכר לכל מי שעבד עם AsyncStorage ו-redux-persist). אני נתקלתי בבאג הזה בדיוק כשהשקנו פיצ׳ר login ב-2024, וזה היה הזרז שדחף אותנו לעבור.
שימו לב לשימוש ב-createSyncStoragePersister במקום ה-async. זה אפשרי רק בזכות ה-API הסינכרוני של MMKV, ומחסך לכם serialization של Promise בכל קריאה.
New Architecture, Hermes ו-Nitro Modules
החל מגרסה 3.0, react-native-mmkv עבר ל-Nitro Modules, דור חדש של JSI bindings שגם הוא מבית מארק רוסבי. Nitro מספק type-safety אוטומטי בין TypeScript ל-C++, ביצועי קריאה משופרים בכ-30% נוספים, ותמיכה מלאה ב-Bridgeless mode של React Native 0.74+. ראו גם את המאמר על Reanimated 4 ו-Worklets שמשתמש בעקרונות דומים.
אם אתם מריצים את React Native 0.76+ עם newArchEnabled=true ב-gradle.properties וב-Podfile.properties.json, MMKV פשוט עובד. אין הגדרות מיוחדות. ב-Hermes (מנוע ה-JS הדיפולטי החל מ-RN 0.70), הקריאות ל-MMKV הופכות אפילו יותר מהירות בזכות אופטימיזציות של inline cache.
בנצ׳מרקים ושיקולי ביצועים
הבדיקות שמופיעות בריפו הרשמי של react-native-mmkv מודדות 1,000 פעולות get/set רצופות. התוצאות (Pixel 7, Android 14):
MMKV, 1,000 כתיבות: 23ms
AsyncStorage, 1,000 כתיבות: 720ms
MMKV, 1,000 קריאות: 7ms
AsyncStorage, 1,000 קריאות: 510ms
אבל הסיפור האמיתי הוא לא רק המספרים. מאחר ש-MMKV הוא סינכרוני, אפשר לגשת אליו בתוך render(), בתוך selectors של Zustand, ואפילו בתוך middleware של navigation, בלי לדאוג ל-loading states. זה משנה את הארכיטקטורה לגמרי: אין צורך ב-context provider שמחכה ל-AsyncStorage rehydration לפני הצגת ה-app.
שיקול חשוב: MMKV טוען את כל הקובץ לזיכרון בעת יצירת ה-instance. אם אתם מאחסנים מאות מגה-בייט (לא מומלץ), זמן ה-startup עלול לעלות. הגבלה מעשית, שמרו את ה-instance מתחת ל-50MB. למידע מובנה גדול יותר, עברו ל-SQLite (Drizzle, WatermelonDB) או למערכת קבצים (expo-file-system).
שאלות נפוצות
האם MMKV באמת מהיר יותר מ-AsyncStorage?
כן. בבדיקות הרשמיות MMKV מהיר פי 25 עד 30 בקריאות וכתיבות, אבל היתרון העיקרי הוא ה-API הסינכרוני שמסיר את הצורך ב-Promises וב-loading states בעת אתחול האפליקציה.
האם אפשר להשתמש ב-MMKV עם Expo Go?
לא. MMKV מכיל קוד נייטיב ב-C++ ולכן דורש Expo Development Client או EAS Build. הריצו npx expo install react-native-mmkv ולאחר מכן npx expo prebuild או eas build --profile development.
האם MMKV מצפין את הנתונים כברירת מחדל?
לא. הצפנה היא opt-in: יש להעביר encryptionKey בעת יצירת ה-instance. ההצפנה היא AES-256 ברמת קובץ ה-mmap, ויש לאחסן את המפתח עצמו ב-Keychain או Keystore באמצעות expo-secure-store או react-native-keychain.
האם MMKV תומך ב-New Architecture של React Native?
כן, באופן מלא. החל מגרסה 3.x הספרייה משתמשת ב-Nitro Modules, וכוללת תמיכה ב-Bridgeless mode, ב-Fabric וב-TurboModules. אין צורך בקונפיגורציה נוספת מעבר להפעלת newArchEnabled.
איך עושים הגירה מ-AsyncStorage בלי לאבד נתונים?
הריצו פונקציית הגירה חד-פעמית ב-bootstrap של האפליקציה: קראו את כל המפתחות מ-AsyncStorage עם getAllKeys() ו-multiGet(), כתבו אותם ל-MMKV עם storage.set(), סמנו flag הגירה ב-MMKV עצמו, ולבסוף נקו את AsyncStorage.
מתי כדאי להעדיף SQLite על פני MMKV?
כאשר צריך שאילתות מורכבות, אינדקסים, joins או אחסון של מעל 50MB. MMKV מתאים ל-key-value flat: tokens, הגדרות, cache קטן ו-flags. למודלים יחסיים השתמשו ב-Drizzle, WatermelonDB או expo-sqlite.
FlashList v2 הוא שכתוב מהיסוד של ספריית הרשימות של Shopify, שנבנה במיוחד עבור הארכיטקטורה החדשה של React Native. במדריך המעשי הזה נעבור על כל מה שצריך לדעת כדי לעבור מ-FlatList או מ-FlashList v1 לגרסה החדשה ב-2026: דרישות, שינויים, Masonry, אופטימיזציות ופתרון בעיות.
מדריך מעשי ל-React Native Reanimated 4 ב-2026: Worklets, CSS Animations, Shared Element Transitions ו-Layout Animations — עם דוגמאות קוד אמיתיות, מדריך מיגרציה מ-Reanimated 3 וטיפים לביצועים של 60+ FPS.