从 AsyncStorage 平滑迁移到 react-native-mmkv:完整迁移脚本与实战指南
发布时间:2026/9/25 2:53:14来源:尧图网络
【免费下载链接】react-native-mmkv⚡️ The fastest key/value storage for React Native. ~30x faster than AsyncStorage!项目地址https://gitcode.com/gh_mirrors/re/react-native-mmkv点击查看免费下载本文基于 react-native-mmkv 官方迁移指南docs/MIGRATE_FROM_ASYNC_STORAGE.md展开详细讲解如何编写一段可复用的迁移脚本把 AsyncStorage 中已有的全部键值对复制到 MMKV并安全地清理旧数据。读完本文你将掌握在真实 App 启动流程中集成迁移逻辑、处理布尔值与字符串的类型转换、规避迁移失败风险以及如何结合仓库源码理解 MMKV 的底层 API 与配置选项实现一次性的平滑过渡。为什么需要从 AsyncStorage 迁移到 MMKVAsyncStorage 是 React Native 社区长期使用的异步键值存储方案但其底层基于 Bridge 通信与异步 I/O读写性能存在明显瓶颈。react-native-mmkv 则是通过 JSI 与 C Nitro Modules 直接桥接腾讯 MMKV 原生库见 README.md提供完全同步的读写调用不依赖 async/await、Promise 与 Bridge官方称其读取性能约为 AsyncStorage 的 30 倍。对于已经积累了用户数据的老项目直接切换存储方案意味着旧数据丢失因此需要一套一次性迁移脚本把 AsyncStorage 中的所有键值对读取出来写入 MMKV随后从 AsyncStorage 中删除并用一个标记位记录迁移完成状态。迁移方案总览官方指南给出了两个文件组成的完整方案storage.ts定义全局共享的 MMKV 实例、迁移状态标记位以及核心的migrateFromAsyncStorage()迁移函数App.tsx在应用启动时检查是否已迁移若未迁移则利用InteractionManager.runAfterInteractions在首帧渲染完成后再执行迁移迁移期间显示加载指示器。整体流程如下App 启动读取 MMKV 中的hasMigratedFromAsyncStorage标记若标记不存在值为undefined/false进入迁移中状态显示加载指示器后台异步执行迁移遍历 AsyncStorage 全部键 → 读取值 → 类型转换后写入 MMKV → 删除 AsyncStorage 中的旧值全部完成后写入hasMigratedFromAsyncStorage true更新 React 状态渲染正式应用界面一段时间后所有用户都已完成迁移移除标记位与迁移逻辑。第一步编写 storage.ts 迁移脚本以下是官方指南提供的storage.ts完整实现import AsyncStorage from react-native-async-storage/async-storage; import { createMMKV } from react-native-mmkv; export const storage createMMKV(); // TODO: Remove hasMigratedFromAsyncStorage after a while (when everyone has migrated) export const hasMigratedFromAsyncStorage storage.getBoolean( hasMigratedFromAsyncStorage, ); // TODO: Remove hasMigratedFromAsyncStorage after a while (when everyone has migrated) export async function migrateFromAsyncStorage(): Promisevoid { console.log(Migrating from AsyncStorage - MMKV...); const start global.performance.now(); const keys await AsyncStorage.getAllKeys(); for (const key of keys) { try { const value await AsyncStorage.getItem(key); if (value ! null) { if ([true, false].includes(value)) { storage.set(key, value true); } else { storage.set(key, value); } AsyncStorage.removeItem(key); } } catch (error) { console.error( Failed to migrate key ${key} from AsyncStorage to MMKV!, error, ); throw error; } } storage.set(hasMigratedFromAsyncStorage, true); const end global.performance.now(); console.log(Migrated from AsyncStorage - MMKV in ${end - start}ms!); }逐段解读1. 创建全局共享的 MMKV 实例export const storage createMMKV();createMMKV()不传任何配置时会创建一个使用默认实例 IDmmkv.default的实例。从源码 createMMKV.ts 可以看到实例创建后还会自动挂载内存警告监听addMemoryWarningListener与内容变更监听addContentChangedListener。官方建议在整个 App 内复用同一个实例而不是每次使用时新建因此这里以模块级export的形式共享。2. 迁移标记位export const hasMigratedFromAsyncStorage storage.getBoolean( hasMigratedFromAsyncStorage, );由于getBoolean在键不存在时返回undefined见 MMKV.nitro.ts所以首次启动时该值为undefined恰好可以作为尚未迁移的判断依据。注释中的 TODO 提醒当所有用户都完成迁移后应将标记位与迁移逻辑一并移除避免无谓的开销。3. 遍历并转换数据AsyncStorage 中存储的所有值本质上都是字符串而 MMKV 支持四种原生类型boolean | string | number | ArrayBuffer见 MMKV.nitro.ts。因此迁移时需要做类型判断if ([true, false].includes(value)) { storage.set(key, value true); } else { storage.set(key, value); }若字符串恰好是true或false则按布尔值写入 MMKV后续可用getBoolean读取其余字符串一律按字符串写入后续用getString读取。这是官方迁移脚本的核心逻辑AsyncStorage 无类型概念而 MMKV 有类型区分转换结果直接决定了迁移后读取 API 的选择。需要注意此脚本默认不迁移数字类型——AsyncStorage 中的42会以字符串42写入 MMKV。如果你的旧数据大量使用数字可以在迁移时扩展判断例如用isNaN检测数字字符串再storage.set(key, Number(value))但官方脚本保持简单将类型归一化的工作交给业务侧。4. 边迁边删AsyncStorage.removeItem(key);每成功迁移一个键立即从 AsyncStorage 中删除对应旧值避免迁移中断后重复数据残留。注意这里没有await属于发后即忘式删除官方如此书写可保持循环体同步推进如需严格保证删除完成后再进入下一个键可加上await。5. 错误处理} catch (error) { console.error( Failed to migrate key ${key} from AsyncStorage to MMKV!, error, ); throw error; }单个键迁移失败会打印包含键名的错误日志并抛出异常中断整个迁移过程。这个设计意图是快速失败与其静默跳过部分数据造成迁移不完整不如让上层感知并决定处理策略详见下文 App.tsx 的错误处理讨论。6. 耗时统计const start global.performance.now(); // ...迁移逻辑... const end global.performance.now(); console.log(Migrated from AsyncStorage - MMKV in ${end - start}ms!);利用global.performance.now()统计整个迁移耗时并打印日志便于上线初期观察迁移对启动性能的影响。第二步在 App.tsx 中接入迁移流程官方指南提供了App.tsx的集成示例... import { hasMigratedFromAsyncStorage, migrateFromAsyncStorage } from ./storage; ... export default function App() { // TODO: Remove hasMigratedFromAsyncStorage after a while (when everyone has migrated) const [hasMigrated, setHasMigrated] useState(hasMigratedFromAsyncStorage); ... useEffect(() { if (!hasMigratedFromAsyncStorage) { InteractionManager.runAfterInteractions(async () { try { await migrateFromAsyncStorage() setHasMigrated(true) } catch (e) { // TODO: fall back to AsyncStorage? Wipe storage clean and use MMKV? Crash app? } }); } }, []); if (!hasMigrated) { // show loading indicator while app is migrating storage... return ( View style{{ justifyContent: center, alignItems: center }} ActivityIndicator colorblack / /View ); } return ( YourAppsCode / ); }几个关键设计点1. 用useState初始化同步状态const [hasMigrated, setHasMigrated] useState(hasMigratedFromAsyncStorage);storage.getBoolean(...)是同步调用因此hasMigratedFromAsyncStorage在组件首次渲染时即为最终值useState初始值可以直接用它赋值无需异步加载。这正是 MMKV 相比 AsyncStorage 的优势——异步存储往往需要先await读取再 setState。2. 用InteractionManager.runAfterInteractions延迟迁移InteractionManager.runAfterInteractions(async () {迁移过程涉及大量异步 I/O若在首帧渲染前执行会阻塞用户看到界面。runAfterInteractions会等所有动画与交互完成后才执行回调把迁移对启动体验的影响降到最低。3. 迁移期间展示加载指示器if (!hasMigrated) { return ( View style{{ justifyContent: center, alignItems: center }} ActivityIndicator colorblack / /View ); }迁移未完成时只渲染一个居中的ActivityIndicator防止业务代码在迁移中途读取到不完整的数据。迁移完成后setHasMigrated(true)触发重渲染正式界面才挂载。4. 失败兜底策略TODO 留白} catch (e) { // TODO: fall back to AsyncStorage? Wipe storage clean and use MMKV? Crash app? }官方在此保留了决策空间失败后是回退到 AsyncStorage、清空 MMKV 重新迁移还是直接崩溃这取决于你的业务对数据完整性的要求。一种稳妥做法是保留一个全局开关例如useMMKVFlag迁移失败时降级到 AsyncStorage 继续提供服务同时在下一次启动时重试迁移。源码级原理补充理解createMMKV与 MMKV API为了在迁移后用好 MMKV有必要从源码层面理解几个关键点。createMMKV 的默认行为与配置项从 createMMKV.ts 可知不传配置时使用工厂的默认实例 IDmmkv.defaultiOS 上若未显式指定path而Info.plist配置了 App Group则会自动使用 App Group 目录便于与 App Clips、扩展共享数据实例创建后自动注册内存警告监听与内容变更监听。createMMKV接受完整的Configuration对象定义见 MMKVFactory.nitro.ts配置项类型默认值说明idstringmmkv.default实例 ID多实例时必须使用不同 IDpathstring?undefined$(Documents)/mmkv/存储根目录iOS 下可由 App Group 决定encryptionKeystring?undefined加密密钥AES-128 最长 16 字节AES-256 最长 32 字节encryptionTypeAES-128 \| AES-256AES-128加密算法modesingle-process \| multi-processsingle-process多进程共享App Clip/扩展/小组件时用multi-processreadOnlyboolean?false只读模式set()会抛错compareBeforeSetboolean?false写入前比较新旧值相同则跳过磁盘写入recoveryStrategydiscard-on-error \| recover-on-errorundefined存储损坏时的恢复策略例如若迁移后需要为敏感数据加密可以这样创建实例export const storage createMMKV({ id: secure-storage, encryptionKey: my-encryption-key!, encryptionType: AES-256, });迁移后如何读取数据MMKV 提供了与迁移脚本对应的类型化读取 API见 MMKV.nitro.tsstorage.getString(user.name) // string | undefined storage.getBoolean(is-dark-mode) // boolean | undefined storage.getNumber(user.age) // number | undefined storage.getBuffer(someToken) // ArrayBuffer | undefined storage.contains(user.name) // 键是否存在 storage.getAllKeys() // 全部键 storage.remove(user.name) // 删除单个键 storage.clearAll() // 清空在迁移脚本中字符串一律通过storage.set(key, value)写入因此读取时应使用getString被识别为布尔值的键则用getBoolean读取。MMKV 实例间迁移importAllFrom如果你的应用已有多个 MMKV 实例例如按用户区分官方 API 还提供了实例间的数据导入方法const importedCount storage.importAllFrom(otherStorage);importAllFrom返回导入的键值对数量见 MMKV.nitro.ts。虽然本迁移方案是从 AsyncStorage 到 MMKV但理解该 API 有助于后续做 MMKV 实例合并、多实例统一等演进。迁移脚本在测试环境的表现仓库为 Jest/Vitest 测试环境自动提供 mock 的 MMKV 实例见 createMockMMKV.ts其中set/get基于内存Map实现getBoolean对非布尔值返回undefined。这意味着你可以在单测中直接调用migrateFromAsyncStorage()而无需初始化原生模块方便为迁移逻辑编写测试用例可参考 hooks.test.tsx 与 contentChangedListener.test.ts 的测试组织方式。迁移完成后清理与最佳实践1. 移除标记位与迁移代码按官方注释的 TODO 指引当所有活跃用户都完成迁移后应删除storage.ts中的hasMigratedFromAsyncStorage常量与migrateFromAsyncStorage()函数App.tsx中的useEffect迁移逻辑、加载指示器分支以及相关的InteractionManager与useState代码。同时可以从依赖中移除react-native-async-storage/async-storage彻底摆脱旧的异步存储。2. 保持存储读取路径一致迁移脚本对布尔值的判断依赖旧数据的存储格式。若旧代码曾用AsyncStorage.setItem(flag, 1)这类非标准布尔表示迁移后读取会出现类型不匹配需要在迁移函数中补充对应转换规则。3. 用 Hooks 简化后续读写迁移完成后推荐使用仓库提供的 Hooks 进一步简化组件内的存储访问const [username, setUsername] useMMKVString(user.name) const [age, setAge] useMMKVNumber(user.age) const [isDarkMode, setIsDarkMode] useMMKVBoolean(is-dark-mode)这些 Hooks 的实现见 hooks 目录如 useMMKVString.ts、useMMKVListener.ts它们会自动监听值变化并驱动组件重渲染相比手动订阅更加简洁。4. 关注迁移失败的降级方案由于迁移期间应用处于只显示加载指示器的状态务必保证迁移逻辑健壮建议在真机与弱网/存储满等异常环境下提前验证getAllKeys/getItem/removeItem的失败路径并决定好失败时的兜底策略而不是把 TODO 留到线上事故之后。总结从 AsyncStorage 迁移到 react-native-mmkv 是典型的一次性数据搬迁任务核心要点可以归纳为类型转换AsyncStorage 只有字符串MMKV 区分boolean | string | number | ArrayBuffer迁移时需按true/false识别布尔值边迁边删每迁移一个键立即removeItem避免重复数据标记位驱动用hasMigratedFromAsyncStorage布尔标记保证迁移只执行一次迁移完成后可整体清理启动期编排用InteractionManager.runAfterInteractions延迟迁移、用加载指示器屏蔽中间态、用performance.now()量化耗时失败兜底明确迁移失败后的策略回退 AsyncStorage / 清空重迁 / 崩溃避免数据不完整。参考仓库中的官方文档 docs/MIGRATE_FROM_ASYNC_STORAGE.md、核心 API 定义 MMKV.nitro.ts 与 MMKVFactory.nitro.ts以及项目总览 README.md即可完成从方案设计到落地的全部工作。赞分享【免费下载链接】react-native-mmkv⚡️ The fastest key/value storage for React Native. ~30x faster than AsyncStorage!项目地址https://gitcode.com/gh_mirrors/re/react-native-mmkv点击查看免费下载相关推荐React Native MMKV迁移终极指南从AsyncStorage到30倍性能提升的完整方案React Native MMKV迁移终极指南从AsyncStorage到30倍性能提升的完整方案 React Native MMKV是目前React NatWebdriverIO 迁移指南从 Protractor 平滑迁移到 WebdriverIO 的完整实战教程WebdriverIO 迁移指南从 Protractor 平滑迁移到 WebdriverIO 的完整实战教程 WebdriverIO 是适用于 Node.js测试质量保障Sinon 迁移指南从 Spy 平滑迁移到 Fake 的完整实战手册Sinon 迁移指南从 Spy 平滑迁移到 Fake 的完整实战手册 本指南以 Sinon 官方文档 docs/concepts/spies/migratin测试开发工具上一篇终极视频元数据修复指南Captura错误检测与自动校正技术全解析下一篇2023-11-15 代码改进日志创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网