Publishing Hot Updates
Now that your app can detect updates, let's learn how to publish and update it. See the flow below:
- We first need to build a native release version. Before building, ensure
react-native-updateis integrated, tested, and works correctly. For Android, disablecrunchPngs. See documentation for iOS Build and Android Build. After building, runcresc uploadIpaorcresc uploadApkto upload the package to Cresc servers to serve as the baseline for delta comparisons. Keep a copy of this installation package; the package distributed to usersmust be strictly identicalto the uploaded one. We recommend using git tags for native versioning (e.g.,v1.0.0). - Iterate on your business logic over the baseline (add/remove JS code, static assets). Run
cresc bundleto generate and publish a hot update without recompiling the native app. We recommend using git tags for hot update versioning (e.g.,v1.0.1). - If there are native changes during iteration, you must publish and upload a new native baseline version (repeat step 1, but set a different native version number). You can maintain just one native baseline or multiple versions concurrently.
Publishing Native Baseline Version
iOS
Refer to Running On Device to ensure you are using the offline bundle.
Follow the standard flow to archive the .ipa file:
- In Xcode, select a real device or Generic iOS Device.
- Go to Product - Archive.
- After Archiving, select
Exportto generate the .ipa file. - Run the following command to upload it:
The CFBundleShortVersionString in ios/[project]/Info.plist will be recorded as the packageVersion.
You can now upload this version to the App Store, or test it on devices via TestFlight. Note: Testing hot updates directly via Xcode is not supported yet.
If you re-archive later (e.g., modifying native code/configs), you must change the version number, and uploadIpa again. Otherwise, identically versioned native packages will fail to receive hot updates due to mismatched build timestamps.
Android
Set up signing per Android Signed APK. Run ./gradlew assembleRelease or ./gradlew aR in the android folder. The APK will be under android/app/build/outputs/apk/release/app-release.apk.
Upload it via:
The versionName in android/app/build.gradle is recorded as the packageVersion.
You can now publish this version to app markets or install it directly for testing.
If you rebuild native code later, you must change the version number, and uploadApk again. Otherwise, hot updates will fail due to build timestamp mismatches.
Harmony
Use DevEco-Studio and go to Build => Build Hap(s)/App(s) => Build App(s). The package will be in harmony/build/outputs/default/harmony-default-unsigned.app.
Run:
The App's versionName in harmony/AppScope/app.json5 is recorded as the packageVersion.
Publish to the Huawei AppGallery, or test on device via hdc shell. Rebuilds require version increments to prevent build timestamp mismatches.
Publishing Hot Update Version
Modify a line of code, and run cresc bundle --platform <ios|android|harmony> to generate a new hot update version.
If you use frameworks without index.js like modern expo, the bundle command will fail. Manually create an index.js file importing the framework's entry file, referring to main in package.json. For expo, index.js looks like:
Input Y to upload immediately, or run cresc publish --platform android build/output/android.1459850548545.ppk later.
The version is stored on the server, but users cannot see it until you bind native packages to it.
Input Y to bind immediately, or run cresc update --platform <ios|android|harmony> later to bind previously uploaded versions. You can also drag and drop native versions to matching hot updates on the web dashboard.
After binding, the server takes a few seconds to generate diff patches, and clients will receive updates.
To publish new updates thereafter, repeatedly run cresc bundle without recompiling native code.
Congratulations! You have completed the hot update integration.
Canary Release (Gradual Rollout)
Canary releases mitigate risk by gradually expanding the update scope to test stability.
What is a Canary Release?
Before pushing updates globally, you push them to a small subset (e.g., 5%, 10%) of users, observe their metrics, and gradually widen the scope to 100%.
Benefits
- Lower Risk: Bugs only affect small subsets, enabling swift rollbacks.
- Verify Stability: Observe performance across varied real-world networking environments.
- Smooth Transitions: Prevents severe server CPU usage spikes during mass updates.
- Fast Recovery: Halts rollouts immediately minimizing global impact.
How it Works
When you configure a canary percentage (e.g., 10%), update queries calculate a hash using the device's UUID:
- Users within the bucket receive the newest updates.
- Users outside receive the previous full version or no update.
- The hash remains stable; multiple checks won't flip a user's bucket state.
Usage
Web Dashboard
- Log into the Cresc Dashboard.
- Select App and Native Version.
- Click "Publish".
- Adjust the rollout percentage.
Command Line
Review the rollout parameter in the CLI docs.
Notes
Important: Canary versions form independent bindings with Native packages.
- One Canary Version At A Time: Each Native Version can bind to one Canary update (<100%) and one Full update concurrently.
- Priority: Users inside the canary bucket receive the canary update. Others receive the Full update.
- Promoting to Full: Bumping the percentage to 100% promotes the canary to a full release automatically, replacing any older full releases.
- Client Requirements: Features require
react-native-update>= 10.32.0.