Skip to content

feat: adds release mode docs to repack doc #108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 219 additions & 1 deletion components/zephyr/repack/start-from-scratch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -536,4 +536,222 @@ You should see the applicaiton running in the iOS emulator:

<Image src="/host-app-ios.webp" alt="Zephyr Cloud Minimal example running in iOS emulator" />

The process should be the same for Android.
The process should be the same for Android.

## Running the application in release mode with Zephyr

By default, the HostApp loads miniapp bundles from a local development server (e.g. localhost). To run the app in production/release mode without using the Zephyr development environment, you must replace those local URLs with the Zephyr Cloud URLs for each miniapp. This ensures the HostApp fetches the miniapp bundles directly from the Zephyr-hosted endpoints. The process involves configuring your Zephyr environment - and zephyr will auto-retrieving the correct remote URLs as well as updating the HostApp’s module federation configuration. Once completed, you can build and launch the app in release mode normally (e.g. via Xcode or react-native release build), and it will load miniapps from the Zephyr Cloud URLs instead of localhost.

To successfully run the HostApp in release mode using Zephyr-hosted MiniApps, you need to have a Zephyr environment configured for your project (such as production or staging). Each MiniApps (remote module), along with the HostApp itself, must be registered within this environment. For step-by-step setup guidance, refer to the [Zephyr Environment Guide](../../how-to/environments.mdx)

### Steps

Follow these steps to configure and run the HostApp in release mode with Zephyr:

Configure the Zephyr environment:

1. Change your configs to divide debug builds and release builds:

- In the HostApp and MiniApp, change the `rspack.config.mjs` file to add a `ZC` variable:

```js title="HostApp/rspack.config.mjs"{9,17,72}
import path from 'node:path';
import {fileURLToPath} from 'node:url';
import * as Repack from '@callstack/repack';
import {withZephyr} from 'zephyr-repack-plugin';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);


const USE_ZEPHYR = Boolean(process.env.ZC);
/**
* Rspack configuration enhanced with Re.Pack defaults for React Native.
*
* Learn about Rspack configuration: https://rspack.dev/config/
* Learn about Re.Pack configuration: https://re-pack.dev/docs/guides/configuration
*/

const config = env => {
const { platform, mode } = env
return {
context: __dirname,
entry: './index.js',
resolve: {
// 1. Understand the file path of ios and android file extensions
// 2. Configure the output to be as close to Metro as possible
...Repack.getResolveOptions(),
},
output: {
// Unsure - for module federation HMR and runtime?
uniqueName: 'react-native-host-app',
},
module: {
rules: [
...Repack.getJsTransformRules(),
...Repack.getAssetTransformRules(),
],
},
plugins: [
new Repack.RepackPlugin({
platform,
}),
new Repack.plugins.ModuleFederationPluginV2({
name: 'HostApp',
filename: 'HostApp.container.js.bundle',
dts: false,
remotes: {
MiniApp: `MiniApp@http://localhost:9001/${platform}/MiniApp.container.js.bundle`,
},
shared: {
react: {
singleton: true,
version: '19.0.0',
eager: true,
},
'react-native': {
singleton: true,
version: '0.78.0',
eager: true,
}
},
}),
// Supports for new architecture - Hermes can also use JS, it's not a requirement, it will still work the same but it's for performance optimization
new Repack.plugins.HermesBytecodePlugin({
enabled: mode === 'production',
test: /\.(js)?bundle$/,
exclude: /index.bundle$/,
}),
],
}
};

export default USE_ZEPHYR ? withZephyr()(config) : config;
```

```js title="MiniApp/rspack.config.mjs"{9,19,68}
import path from 'node:path';
import {fileURLToPath} from 'node:url';
import * as Repack from '@callstack/repack';
import {withZephyr} from 'zephyr-repack-plugin';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const USE_ZEPHYR = Boolean(process.env.ZC);
const STANDALONE = Boolean(process.env.STANDALONE);

/**
* Rspack configuration enhanced with Re.Pack defaults for React Native.
*
* Learn about Rspack configuration: https://rspack.dev/config/
* Learn about Re.Pack configuration: https://re-pack.dev/docs/guides/configuration
*/

const config = env => {
const {platform, mode} = env;
return {
mode,
context: __dirname,
entry: './index.js',
resolve: {
...Repack.getResolveOptions(),
},
output: {
uniqueName: 'react-native-mini-app',
},
module: {
rules: [
...Repack.getJsTransformRules(),
...Repack.getAssetTransformRules({inline: true}),
],
},
plugins: [
new Repack.RepackPlugin(),
new Repack.plugins.ModuleFederationPluginV2({
name: 'MiniApp',
filename: 'MiniApp.container.js.bundle',
dts: false,
exposes: {
'./App': './App.tsx',
},
shared: {
react: {
singleton: true,
version: '19.0.0',
eager: STANDALONE,
},
'react-native': {
singleton: true,
version: '0.78.0',
eager: STANDALONE,
},
},
}),
new Repack.plugins.HermesBytecodePlugin({
enabled: mode === 'production',
test: /\.(js)?bundle$/,
exclude: /index.bundle$/,
}),
],
};
};

export default USE_ZEPHYR ? withZephyr()(config) : config;

```

- `ZC` is used to indicate that the bundles are for Zephyr Cloud.

- Now, when you run or bundle with `ZC=1`, the bundles will be uploaded to Zephyr Cloud.

2. Add bundle scripts to the HostApp and MiniApp:

- In the HostApp and MiniApp, add the following scripts to the package.json files:

```json title="HostApp/package.json"
"scripts": {
"bundle": "pnpm run bundle:ios && pnpm run bundle:android",
"bundle:ios": "react-native bundle --platform ios --dev false --entry-file index.js",
"bundle:android": "react-native bundle --platform android --dev false --entry-file index.js"
}
```

```json title="MiniApp/package.json"
"scripts": {
"bundle": "pnpm run bundle:ios && pnpm run bundle:android",
"bundle:ios": "react-native bundle --platform ios --dev false --entry-file index.js",
"bundle:android": "react-native bundle --platform android --dev false --entry-file index.js"
}
```

2. Bundle HostApp and MiniApps, and upload to Zephyr Cloud:

- Bundle the MiniApp:

```bash
ZC=1 pnpm --filter MiniApp bundle
```

- Bundle the HostApp:

```bash
ZC=1 pnpm --filter HostApp bundle
```

- Command run with `ZC=1` will upload the bundles to Zephyr Cloud.


3. Build and run the HostApp in release mode:

- For Android, you can use the following command from the HostApp android directory:

```bash
ZC=1 ./gradlew assembleRelease
```

{/* TODO: set ZC for iOS */}
{/* - For iOS, you can use the following command: */}
Copy link
Contributor

@zmzlois zmzlois May 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to fix this


- The HostApp will now load each miniapp bundle from the specified Zephyr Cloud URLs instead of localhost. Verify that the app launches correctly and that each MiniApp is fetched successfully from the remote URL.

By following these steps, you can run your HostApp in production mode with the Zephyr, using the remote bundles hosted on Zephyr Cloud.