react-native-ota-hot-update

repository·main·Indexed 20 days ago

https://github.com/vantuan88291/react-native-ota-hot-update

A module for managing in-app hot updates (JS bundle updates) for React Native applications. It provides a self-hosted alternative to services like Code Push, allowing developers to host bundles on their own servers or Git repositories. Features include automatic crash rollbacks, bundle history management, and support for both Android and iOS (including Swift and Objective-C) and Expo.

Tokens
16.6K
Snippets
48
Records
63
Agent score
72%

What's inside react-native-ota-hot-update

  1. How OTA Updates work (Conceptual Flow)

    main

    The OTA update process follows this lifecycle:

    1. Download & Install: The app fetches an update.json from your server/Git. If a new version is found, it downloads bundle.zip. The native module unzips this to a versioned folder and saves the path to local storage (SharedPrefs/UserDefaults).
    2. App Startup: When the app starts, the native module checks local storage for a saved OTA bundle path. If a valid path exists and the file is on disk, it loads the OTA bundle. Otherwise, it falls back to the built-in bundle.
    3. Crash Auto-Rollback: If the app crashes within 2 seconds of starting with a new bundle, the native module automatically restores the previous bundle path and restarts the app with the safe version.
  2. Enhanced Bundle Management (v2.4.0-rc.1 Preview)

    main

    The experimental 2.4.0-rc.1 release introduces advanced bundle lifecycle management.

    Key Features:

    • Configurable bundle history: Use maxBundleVersions to limit how many versions are kept.
    • Automatic cleanup: Older bundles are removed automatically when the limit is reached.
    • New APIs:
      • getBundleList(): Retrieve available bundles.
      • deleteBundleById(): Remove a specific bundle.
      • clearAllBundles(): Wipe all downloaded bundles.

    To install the preview version:

    yarn add react-native-ota-hot-update@2.4.0-rc.1
  3. Reload the application during development

    main

    After making changes to your code (e.g., in App.tsx), use the following shortcuts to reload the app and see your changes:

    • Android: Press the <kbd>R</kbd> key twice, or open the Developer Menu (<kbd>Ctrl</kbd> + <kbd>M</kbd> on Windows/Linux, or <kbd>Cmd ⌘</kbd> + <kbd>M</kbd> on macOS) and select "Reload".
    • iOS: Press <kbd>Cmd ⌘</kbd> + <kbd>R</kbd> within the iOS Simulator.
  4. Configure Strapi CMS for OTA Updates

    main

    To manage React Native OTA updates via a custom backend, you can use Strapi. You need to create separate collection types for each platform to filter bundles by the app's current version.

    1. Create Collection Types

    Create two collection types: android and ios.

    2. Define Schema Fields

    Each collection must include the following fields to support the update logic:

    • targetVersion (String): The app version this bundle is compatible with (e.g., 1.0.0).
    • enable (Boolean): To toggle whether this specific bundle is active.
    • required (Boolean): To indicate if the update is mandatory.
    • bundle (Media/File): The actual OTA bundle file.
    • silentMY (Boolean): (Optional/Custom) for specific regional silent updates.
    • silentSG (Boolean): (Optional/Custom) for specific regional silent updates.
    • note (String): Information about the update.

    3. Set Permissions

    By default, Strapi collections are private. You must grant public access so the mobile app can query them:

    1. Navigate to Settings > Users & Permissions plugin > Roles > Public.
    2. Find the android and ios collections.
    3. Grant find permissions.
    4. Click Save.
  5. Configure iOS (Objective-C AppDelegate)

    main

    For standard iOS projects using Objective-C, modify AppDelegate.m to return the OTA bundle instead of the default bundle in release mode.

    1. Import the header: #import "OtaHotUpdate.h"
    2. Update the bundle URL logic:
    ```objc
    #import "OtaHotUpdate.h"
    
    // ... inside your AppDelegate methods
    {
    #if DEBUG
      return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@
  6. Configure iOS (Swift AppDelegate)

    main

    For React Native 0.77 or above where AppDelegate is a Swift file, update AppDelegate.swift to use OtaHotUpdate.getBundle() in the bundleURL() method.

    import react_native_ota_hot_update
    
    override func bundleURL() -> URL? {
        #if DEBUG
            RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
        #else
            OtaHotUpdate.getBundle()  // Add this line
        #endif
    }
  7. Configure Android (Kotlin MainApplication.kt)

    main

    For standard Android projects using Kotlin, override getJSBundleFile() in your MainApplication.kt to return the OTA bundle path.

    import com.otahotupdate.OtaHotUpdate
    
    // ... inside ReactNativeHost
    override fun getJSBundleFile(): String? {
      return OtaHotUpdate.bundleJS(this@MainApplication)
    }
  8. Install react-native-ota-hot-update

    main

    Install the core package. If you need to manage download progress, you must also install react-native-blob-util.

    Standard Installation:

    yarn add react-native-ota-hot-update

    With Download Progress Support:

    yarn add react-native-ota-hot-update && yarn add react-native-blob-util

    Note: Hot updates only work in release mode. They will not function in debug mode.

  9. Configure Android (React Native 0.82+)

    main

    In React Native 0.82 or above, you must provide the bundle path to the reactHost configuration in MainApplication.kt.

    override val reactHost: ReactHost by lazy {
      getDefaultReactHost(
        context = applicationContext,
        packageList = PackageList(this).packages,
        jsBundleFilePath = OtaHotUpdate.bundleJS(applicationContext)
      )
    }
  10. Set up a Git repository for Hot Updates

    main

    Follow these steps to prepare your Git repository to host bundle files:

    1. Create and Clone a Repository

    Create a new repository (e.g., OTA-bundle) on GitHub, GitLab, or Bitbucket, then clone it locally:

    git clone https://github\/<your-username>/OTA-bundle.git

    2. Generate and Add Bundle Files

    You must export your React Native or Expo bundles and add them to the repository.

    For React Native CLI:

    "scripts": {
      "export-android": "mkdir -p android/output && react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/output/index.android.bundle --assets-dest android/output",
      "export-ios": "mkdir -p ios/output && react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ios/output/main.jsbundle --assets-dest ios/output"
    }

    For Expo / Expo Bare:

    "scripts": {
      "export-android": "mkdir -p android/output && npx expo export:embed --platform android --entry-file node_modules/expo/AppEntry.js --bundle-output android/output/index.android.bundle --dev false  --assets-dest android/output",
      "export-ios": "mkdir -p ios/output && npx expo export:embed --platform ios --entry-file node_modules/expo/AppEntry.js --bundle-output ios/output/main.jsbundle --dev false  --assets-dest ios/output"
    }

    *Note: For Expo, verify the --entry-file path matches your package.json main entry.

    After generating, copy the android/output or ios/output folders into your cloned repository, then commit and push:

    git add .
    git commit -m "Initial commit with bundle files"
    git push origin main

    Create platform-specific branches to manage updates separately:

    git checkout -b iOS
    git push origin iOS
    
    git checkout -b android
    git push origin android