Build SuperApps in React Native

Kiran Shinde
4 min readJan 6, 2025

--

You might have gone through numerous apps which consists of mini/child apps inside it and without updates from app/play store these apps can receive Ui and functionality changes which are within the guidelines of PlayStore & AppStore

Lets understand how can we builds such SuperApps in React Native with use of Repack with Module Federation

What’s Repack?

Re.Pack is what makes Webpack and Webpack-produced bundle usable in React Native application.

What’s Module Federation?

Module Federation is an architecture, which splits the application into multiple pieces. These pieces are called containers. Similarly to micro-services, Module Federation splits application into a distributed frontends, sometimes referred to as micro-frontends.

Module Federation can help you:

  • Reduce code duplication
  • Improve code maintainability
  • Reduce the overall size of applications
  • Improve application performance

Module Federation has three main components:

  • Exposed Module (Remote App)
  • Host Module (Shell App)
  • Shared dependencies
shared: {
react: {
singleton: true,
eager: STANDALONE,
requiredVersion: '18.2.0',
},
'react-native': {
singleton: true,
eager: STANDALONE,
requiredVersion: '0.72.3',
}
}

API Definition for Shared Dependencies

  • shared (object | [string]): An object or Array of strings containing a list of dependencies that can be shared and consumed by other federated apps.
  • eager (boolean): If true, the dependency will be eagerly loaded and made available to other federated apps as soon as the host application starts. If false, the dependency will be lazily loaded when it is first requested by a federated app.
  • singleton (boolean): If true, the dependency will be treated as a singleton and only a single instance of it will be shared among all federated apps.
  • requiredVersion (string): Specifies the required version of the dependency. If a federated app tries to load an incompatible version of the dependency, two copies will be loaded.

Code Splitting

Code Splitting is a technique that splits the code into multiple files, which can be loaded on demand and in parallel. These chunks are remote by default. We can specify which would be local and which should be remotely fetched in runtime to decrease our delivery bundle size.

ScriptManager is responsible to resolve these local and remote chunks and make it available for app to run smoothly.

More information here…

Assets Handling

Asset handling for mini-apps needs to be carefully decided. Here the best suggested way to have remote assets as we have in webapps. But still if all assets needs to be local (for eg: splash, noInternet assets) can be added with inline: true option to the Assets loader.

This will add image as base64 and would be included in bundle which will eventually increase the bundle size.

More information here…

App Archiecture

Run the projects:

Clone the project from Github Repo

In the root project you can find the below scripts in package.json

  • yarn bootstrap — This would download all the dependencies for your host/mini apps in one go
  • yarn start — This would start your apps. Host on port 8081 and miniapp on 9000 on localhost.

Run Android/iOS host app

  • yarn run:host-app:android
  • yarn run:host-app:ios

Run Android/iOS mini app independently

  • yarn mini-app:android
  • yarn run:mini-app:ios

Create bundle/async chunks for miniapp

  • yarn bundle:mini-app

All remote chunks are stored under <projectRoot>/build/output/<platform>/remotes by default.

For example if button.chunk.bundle is a remote chunk, it will be stored under: <projectRoot>/build/output/ios/remotes/button.chunk.bundle for iOS.

Remote Hosting of Async Chunks

You can use any kind of cloud storage. I have used GCS. We would keep the generated chunks in the below hierarchy. Upload both android and ios folders from <projectRoot>/build/output

The update.json would be used to check for latest version of app and then the specific bundle can be fetched by host app.

{
"app_name": "MiniApp",
"latest_version": "1.0.1",
"versions": {
"1.0.1": {
"buildVersion": 2,
"release_date": "2024-09-29",
"is_mandatory": false,
"release_notes": "Bug fixes and stability improvements."
},
"1.0.0": {
"buildVersion": 1,
"release_date": "2024-09-10",
"is_mandatory": false,
"release_notes": "New features added."
}
}
}

Caching and Versioning

The caching mechanism in Re.Pack prevents scripts over-fetching, which helps reducing bandwidth. Providing storage options to ScriptManager.shared.setStorage will enable caching of downloaded script.

import { ScriptManager, Script } from '@callstack/repack/client';

ScriptManager.shared.setStorage(AsyncStorage);
ScriptManager.shared.addResolver(async (scriptId) => {
const { version } = await getRemoteConfig();

return {
url: Script.getRemoteURL(`http://my-domain.dev/v${version}/${scriptId}`),
};
});

CodeSigning

A code signing plugin can be used to sign chunks so that their integrity can be verified before execution. You should consider code-signing your chunks when you are using CodeSplitting or ModuleFederation and want to deliver parts of your code remotely to the end-user. Compatible with both JS and Hermes-bytecode bundles.

webpack.config.js

import * as Repack from '@callstack/repack';
new Repack.plugins.CodeSigningPlugin({
enabled: mode === 'production',
privateKeyPath: './code-signing.pem',
excludeChunks: /local/,
});

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Kiran Shinde
Kiran Shinde

Written by Kiran Shinde

Trying hands across Tech Stack | Tambola Offline Creator

Responses (5)

Write a response