Skip to content

Commit

Permalink
fix: Eagerly initialize TurboModule because Proxies are slow
Browse files Browse the repository at this point in the history
  • Loading branch information
mrousavy committed Apr 30, 2024
1 parent 26c2ce5 commit 6a21073
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 119 deletions.
98 changes: 0 additions & 98 deletions package/src/LazyTurboModule.ts

This file was deleted.

70 changes: 70 additions & 0 deletions package/src/ModuleNotFoundError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { NativeModules, Platform } from 'react-native';

declare global {
// A react-native internal from TurboModuleRegistry.js
var __turboModuleProxy: unknown | undefined;
}

const BULLET_POINT = '\n* ';

export class ModuleNotFoundError extends Error {
constructor(cause?: unknown) {
// TurboModule not found, something went wrong!
if (global.__turboModuleProxy == null) {
// TurboModules are not available/new arch is not enabled.
// react-native-mmkv 3.x.x requires new arch (react-native >0.74)
// react-native-mmkv 2.x.x works on old arch (react-native <0.74)
throw new Error(
'Failed to create a new MMKV instance: react-native-mmkv 3.x.x requires TurboModules, but the new architecture is not enabled!' +
BULLET_POINT +
'Downgrade to react-native-mmkv 2.x.x if you want to stay on the old architecture.' +
BULLET_POINT +
'Enable the new architecture in your app to use react-native-mmkv 3.x.x. (See https://github.com/reactwg/react-native-new-architecture/blob/main/docs/enable-apps.md)'
);
}

const message =
'Failed to create a new MMKV instance: The native MMKV Module could not be found.';
const suggestions: string[] = [];
suggestions.push(
'Make sure react-native-mmkv is correctly autolinked (run `npx react-native config` to verify)'
);
suggestions.push(
'Make sure you enabled the new architecture (TurboModules) and CodeGen properly generated the react-native-mmkv specs. See https://github.com/reactwg/react-native-new-architecture/blob/main/docs/enable-apps.md'
);
suggestions.push(
'Make sure you are using react-native 0.74.0 or higher, because react-native-mmkv is a C++ TurboModule.'
);
suggestions.push('Make sure you rebuilt the app.');
switch (Platform.OS) {
case 'ios':
case 'macos':
suggestions.push(
'Make sure you ran `pod install` in the ios/ directory.'
);
break;
case 'android':
suggestions.push('Make sure gradle is synced.');
break;
default:
throw new Error(`MMKV is not supported on ${Platform.OS}!`);
}
// check if Expo
const ExpoConstants =
NativeModules.NativeUnimoduleProxy?.modulesConstants?.ExponentConstants;
if (ExpoConstants != null) {
if (ExpoConstants.appOwnership === 'expo') {
// We're running Expo Go
throw new Error(
'react-native-mmkv is not supported in Expo Go! Use EAS (`expo prebuild`) or eject to a bare workflow instead.'
);
} else {
// We're running Expo bare / standalone
suggestions.push('Make sure you ran `expo prebuild`.');
}
}

const error = message + BULLET_POINT + suggestions.join(BULLET_POINT);
super(error, { cause: cause });
}
}
28 changes: 11 additions & 17 deletions package/src/NativeMmkv.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
import { UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes';
import { getLazyTurboModule } from './LazyTurboModule';
import { ModuleNotFoundError } from './ModuleNotFoundError';
import { PlatformContext } from './NativeMmkvPlatformContext';

/**
Expand Down Expand Up @@ -85,21 +85,15 @@ export interface Spec extends TurboModule {
createMMKV(configuration: Configuration): UnsafeObject;
}

let basePath: string | null = null;
let module: Spec | null;
try {
module = TurboModuleRegistry.getEnforcing<Spec>('MmkvCxx');

function getNativeModule(): Spec | null {
if (basePath == null) {
// use default base path from the Platform (iOS/Android)
basePath = PlatformContext.getBaseDirectory();
}

const module = TurboModuleRegistry.get<Spec>('MmkvCxx');

if (module != null) {
// initialize MMKV
module.initialize(basePath);
}

return module;
const basePath = PlatformContext.getBaseDirectory();
module.initialize(basePath);
} catch (cause) {
// TurboModule could not be found!
throw new ModuleNotFoundError(cause);
}
export const MMKVTurboModule = getLazyTurboModule(getNativeModule);

export const MMKVTurboModule = module;
13 changes: 9 additions & 4 deletions package/src/NativeMmkvPlatformContext.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TurboModule, TurboModuleRegistry } from 'react-native';
import { getLazyTurboModule } from './LazyTurboModule';
import { ModuleNotFoundError } from './ModuleNotFoundError';

export interface Spec extends TurboModule {
/**
Expand All @@ -8,7 +8,12 @@ export interface Spec extends TurboModule {
getBaseDirectory(): string;
}

function getModule(): Spec | null {
return TurboModuleRegistry.get<Spec>('MmkvPlatformContext');
let module: Spec | null;
try {
module = TurboModuleRegistry.getEnforcing<Spec>('MmkvPlatformContext');
} catch (e) {
// TurboModule could not be found!
throw new ModuleNotFoundError(e);
}
export const PlatformContext = getLazyTurboModule(getModule);

export const PlatformContext = module;

0 comments on commit 6a21073

Please sign in to comment.