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 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion components/zephyr/repack/start-from-scratch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -536,4 +536,4 @@ 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.
221 changes: 220 additions & 1 deletion docs/recipes/repack-mf.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,226 @@ On the downside, this approach increased coupling, which resulted in challenges

There is also a third solution: using a single NavigationContainer in the host application while exposing navigators from the mini applications. This approach reduces coupling, allowing mini applications to maintain control over their navigators. However, it can lead to undesirable navigation structures, such as deeply nested stack navigators, and a complex linking setup that requires synchronization between the host and mini applications.


## Running the application in release mode with Zephyr

When you are using Zephyr with Re.Pack, the HostApp auto-loads MiniApps' bundles from Zephyr. To run the app in production/release mode with Zephyr, the process involves configuring your Zephyr environment - and `zephyr-repack-plugin` will auto-retrieving the latest deployed remote URLs as well as updating the HostApp’s module federation configuration during the bundling. 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.

We will soon launch `react-native-zephyr-sdk` to auto-rollback, roll-forward MiniApps during runtime. To use `react-native-zephyr-sdk`, you must use `zephyr-repack-plugin` during build time.


### 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:

#### HostApp's configuration

```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;
```

#### MiniApp's configuration

```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 deployed 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 deploy to Zephyr Cloud:

- Bundle the MiniApp:

```bash
ZC=1 pnpm --filter MiniApp bundle
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
ZC=1 pnpm --filter MiniApp bundle
## bundle towards ios
ZC=1 pnpm --filter MiniApp bundle:ios
## bundle towards android
ZC=1 pnpm --filter MiniApp bundle:android

to help us isolate platform deploy

```

- Bundle the HostApp:

```bash
ZC=1 pnpm --filter HostApp bundle
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
ZC=1 pnpm --filter HostApp bundle
## bundle towards ios
ZC=1 pnpm --filter HostApp bundle:ios
## bundle towards android
ZC=1 pnpm --filter HostApp bundle:android

```

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

Choose a reason for hiding this comment

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

Suggested change
- Command run with `ZC=1` will upload the bundles to Zephyr Cloud.
- Command run with `ZC=1` will deploy 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: */}

- The HostApp will now load each MiniApp's 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 Zephyr, using the remote bundles (MiniApps) deployed on Zephyr Cloud.



Expand Down