MMKV ב-React Native 2026: אחסון מהיר וחלופה מלאה ל-AsyncStorage

מדריך מלא ל-react-native-mmkv 2026: התקנה, JSI, הצפנה AES-256, הגירה מ-AsyncStorage ושילוב עם Zustand ו-TanStack Query.

MMKV ל-React Native: מדריך אחסון 2026

עודכן: 24 ביוני 2026

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.xAsyncStorage 2.x
APIסינכרוני (JSI)אסינכרוני (Promises)
מהירות קריאה~0.02ms לערך~0.5 עד 1ms לערך
מהירות כתיבה~0.05ms לערך~1 עד 3ms לערך
טיפוסי נתונים נתמכיםstring, number, boolean, Uint8Arraystring בלבד (JSON.stringify ידני)
הצפנה מובניתAES-256 (ברמת instance)אין (דרוש Keychain חיצוני)
מנועmmap + Protocol BuffersSQLite (אנדרואיד), 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

התקנה ב-Expo (SDK 51+)

npx expo install react-native-mmkv
npx expo prebuild --clean
npx expo run:ios
npx expo 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 שמרכיבים מחדש את הקומפוננטה כשהערך משתנה. שימושי במיוחד להגדרות משתמש:

import { useMMKVString, useMMKVBoolean } from 'react-native-mmkv';

export function ThemeToggle() {
  const [theme, setTheme] = useMMKVString('user.theme', storage);
  const [isDark, setIsDark] = useMMKVBoolean('user.darkMode', storage);

  return (
    <Switch
      value={isDark ?? false}
      onValueChange={setIsDark}
    />
  );
}

הצפנה ב-AES-256 ו-Multi-Instance

אחד היתרונות הגדולים של MMKV הוא הצפנה ברמת ה-instance, ללא תלות בספרייה חיצונית כמו react-native-keychain. כל מה שצריך הוא להעביר encryptionKey ביצירת ה-instance:

import { MMKV } from 'react-native-mmkv';

// instance לא-מוצפן לנתונים כלליים
export const storage = new MMKV({ id: 'app-storage' });

// instance מוצפן לטוקנים וסודות
export const secureStorage = new MMKV({
  id: 'secure-storage',
  encryptionKey: 'replace-with-a-key-from-keychain',
});

secureStorage.set('refreshToken', refreshToken);

אפשר ליצור כמה 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 עצמו, כך שגם אם המשתמש יסיר את האפליקציה ויתקין מחדש, לא יהיה ניסיון הגירה כפול.

לקבלת תמונה רחבה יותר של אופטימיזציות נוספות שמשתלבות עם המעבר, ראו את המדריך שלנו לארכיטקטורה החדשה של React Native ולשיפור ביצועי רשימות עם FlashList v2.

שילוב עם Zustand, Redux ו-TanStack Query

MMKV נטמע באופן טבעי בכל מנהל state פופולרי, פשוט מחליפים את ה-storage adapter ב-persistence layer. הנה דוגמה מלאה עם Zustand persist:

import { create } from 'zustand';
import { persist, createJSONStorage, StateStorage } from 'zustand/middleware';
import { MMKV } from 'react-native-mmkv';

const storage = new MMKV();

const zustandStorage: StateStorage = {
  setItem: (name, value) => storage.set(name, value),
  getItem: (name) => storage.getString(name) ?? null,
  removeItem: (name) => storage.delete(name),
};

type AuthState = {
  token: string | null;
  setToken: (t: string) => void;
  logout: () => void;
};

export const useAuth = create<AuthState>()(
  persist(
    (set) => ({
      token: null,
      setToken: (token) => set({ token }),
      logout: () => set({ token: null }),
    }),
    {
      name: 'auth-storage',
      storage: createJSONStorage(() => zustandStorage),
    }
  )
);

היתרון הכי משמעותי כאן: rehydration קורה סינכרונית בעת אתחול האפליקציה. אין הבהוב של מסך לא מאומת לפני שה-token עולה (תרחיש מוכר לכל מי שעבד עם AsyncStorage ו-redux-persist). אני נתקלתי בבאג הזה בדיוק כשהשקנו פיצ׳ר login ב-2024, וזה היה הזרז שדחף אותנו לעבור.

TanStack Query persister

import { QueryClient } from '@tanstack/react-query';
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client';
import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister';
import { MMKV } from 'react-native-mmkv';

const storage = new MMKV();
const persister = createSyncStoragePersister({
  storage: {
    setItem: (k, v) => storage.set(k, v),
    getItem: (k) => storage.getString(k) ?? null,
    removeItem: (k) => storage.delete(k),
  },
});

const queryClient = new QueryClient();

export function App() {
  return (
    <PersistQueryClientProvider
      client={queryClient}
      persistOptions={{ persister, maxAge: 1000 * 60 * 60 * 24 }}
    >
      {/* ...children */}
    </PersistQueryClientProvider>
  );
}

שימו לב לשימוש ב-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.

אודות הכותב Editorial Team

Our team of expert writers and editors.