Firebase Provider
This guide walks you through setting up `hot-updater` with Firebase in a React Native project. You'll configure the environment, install required packages, and initialize Firebase for seamless updates.
Prerequisites
Before you begin, make sure the following are ready:
- Node.js: Version 20 or later is recommended.
- Firebase Project: Create a new project at Firebase if you don’t have one.
- Firebase Storage: Create a new storage bucket at Firebase if you don’t have one.
- Firestore: Create a new firestore database at Firebase if you don’t have one.
Step 1: Install Required Packages
Run the following command to install dependencies:
npm install hot-updater --save-devStep 2: Configure Firebase
Run the initialization script to start the interactive setup process. Use the following command with your preferred package manager:
npx hot-updater initOnce the setup is complete, a .env file will be generated containing the following keys:
HOT_UPDATER_FIREBASE_PROJECT_ID=your-project-id
HOT_UPDATER_FIREBASE_STORAGE_BUCKET=your-bucket-name
# Project Settings > Service Accounts > New Private Key > Download JSON
GOOGLE_APPLICATION_CREDENTIALS=your-credentials.jsonIf you're not using the react-native-dotenv solution, the tokens from your .env file will not be included in your app bundle and are therefore not exposed to risks. However, if you're still concerned,
please refer to the article below for more details: Security
Step 3: Generated Configurations
During the initialization process, the following file is automatically generated:
hot-updater.config.ts: This file contains the configuration settings for integrating Firebase with your project..env: IMPORTANT: Make sure to set theGOOGLE_APPLICATION_CREDENTIALSenvironment variable to the path of your downloaded Firebase credentials JSON file. This is critical for Firebase authentication to work properly. For more details, see: https://firebase.google.com/docs/admin/setup?hl=en#initialize_the_sdk_in_non-google_environments
HOT_UPDATER_FIREBASE_PROJECT_ID=your-project-id
HOT_UPDATER_FIREBASE_STORAGE_BUCKET=your-bucket-name
# Project Settings > Service Accounts > New Private Key > Download JSON
GOOGLE_APPLICATION_CREDENTIALS=your-credentials.jsonimport { bare } from '@hot-updater/bare';
import {firebaseStorage, firebaseDatabase} from '@hot-updater/firebase';
import * as admin from 'firebase-admin';
import { defineConfig } from 'hot-updater';
import 'dotenv/config';
// https://firebase.google.com/docs/admin/setup?hl=en#initialize_the_sdk_in_non-google_environments
// Check your .env file and add the credentials
// Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to your credentials file path
// Example: GOOGLE_APPLICATION_CREDENTIALS=./firebase-adminsdk-credentials.json
const credential = admin.credential.applicationDefault();
export default defineConfig({
build: bare({
enableHermes: true,
}),
storage: firebaseStorage({
projectId: process.env.HOT_UPDATER_FIREBASE_PROJECT_ID!,
storageBucket: process.env.HOT_UPDATER_FIREBASE_STORAGE_BUCKET!,
credential,
}),
database: firebaseDatabase({
projectId: process.env.HOT_UPDATER_FIREBASE_PROJECT_ID!,
credential,
}),
});Step 4: Add HotUpdater to Your Project
The HotUpdater component wraps your application, enabling seamless delivery of updates and fallback UI during updates. Follow these steps to integrate it into your App.tsx:
import { HotUpdater, getUpdateSource } from "@hot-updater/react-native";
function App() {
return (
<View>
<Text>Hello World</Text>
</View>
);
}
export default HotUpdater.wrap({
source: getUpdateSource("https://<your-firebase-function-url>/api/check-update", {
updateStrategy: "appVersion", // or "fingerprint"
}),
requestHeaders: {
// if you want to use the request headers, you can add them here
},
fallbackComponent: ({ progress, status }) => (
<View
style={{
flex: 1,
padding: 20,
borderRadius: 10,
justifyContent: "center",
alignItems: "center",
backgroundColor: "rgba(0, 0, 0, 0.5)",
}}
>
{/* You can put a splash image here. */}
<Text style={{ color: "white", fontSize: 20, fontWeight: "bold" }}>
{status === "UPDATING" ? "Updating..." : "Checking for Update..."}
</Text>
{progress > 0 ? (
<Text style={{ color: "white", fontSize: 20, fontWeight: "bold" }}>
{Math.round(progress * 100)}%
</Text>
) : null}
</View>
),
})(App);Step 5: Add Babel / Re.Pack / Expo Plugin to Your Project
In this step, you will configure Babel to set the bundle ID at build time. This is necessary for integrating the hot-updater plugin into your project.
Add the following to your babel.config.js file:
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
'hot-updater/babel-plugin',
],
};Add the following to your rspack.config.mjs file:
npm install @hot-updater/repack --save-devimport { HotUpdaterPlugin } from "@hot-updater/repack";
export default {
// ...
plugins: [
new Repack.RepackPlugin(),
new HotUpdaterPlugin()
],
};Add the plugin to your app.json file as shown below:
{
"expo": {
"plugins": [
[
"@hot-updater/react-native",
{
"channel": "production"
}
]
]
}
}npx expo prebuildRun the following command to customize your Babel configuration:
npx expo customize babel.config.jsAdd the following to your babel.config.js file:
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
'hot-updater/babel-plugin',
],
};This process automatically generates the code that needs to be added in Step 6.
Step 6: Add Native Code
To complete the integration of hot-updater, you'll need to add native code modifications for both Android and iOS platforms. This step ensures the hot-updater can interact with your app's underlying framework to apply updates seamlessly.
Android
package com.hotupdaterexample
import android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.hotupdater.HotUpdater
class MainApplication : Application(), ReactApplication {
override val reactHost: ReactHost by lazy {
getDefaultReactHost(
context = applicationContext,
packageList =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage())
},
jsBundleFilePath = HotUpdater.getJSBundleFile(applicationContext),
)
}
override fun onCreate() {
super.onCreate()
loadReactNative(this)
}
}package com.hotupdaterexample
import android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.soloader.OpenSourceMergedSoMapping
import com.facebook.soloader.SoLoader
import com.hotupdater.HotUpdater
class MainApplication : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost =
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage())
}
override fun getJSMainModuleName(): String = "index"
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
override fun getJSBundleFile(): String? {
return HotUpdater.getJSBundleFile(applicationContext)
}
}
override val reactHost: ReactHost
get() = getDefaultReactHost(applicationContext, reactNativeHost)
override fun onCreate() {
super.onCreate()
SoLoader.init(this, OpenSourceMergedSoMapping)
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
load()
}
}
}
package com.hotupdaterexample;
import android.app.Application;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.facebook.soloader.SoLoader;
import java.util.List;
import com.hotupdater.HotUpdater;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new DefaultReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@Override
protected String getJSBundleFile() {
return HotUpdater.Companion.getJSBundleFile(this.getApplication().getApplicationContext());
}
@Override
protected boolean isNewArchEnabled() {
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
}
@Override
protected Boolean isHermesEnabled() {
return BuildConfig.IS_HERMES_ENABLED;
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
DefaultNewArchitectureEntryPoint.load();
}
ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
}iOS
import UIKit
import React
import React_RCTAppDelegate
import ReactAppDependencyProvider
import HotUpdater
@main
class AppDelegate: RCTAppDelegate {
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
self.moduleName = "HotUpdaterExample"
self.dependencyProvider = RCTAppDependencyProvider()
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = [:]
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func sourceURL(for bridge: RCTBridge) -> URL? {
self.bundleURL()
}
override func bundleURL() -> URL? {
#if DEBUG
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
#else
Bundle.main.url(forResource: "main", withExtension: "jsbundle")
HotUpdater.bundleURL()
#endif
}
}#import "AppDelegate.h"
#import <HotUpdater/HotUpdater.h>
#import <React/RCTBundleURLProvider.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.moduleName = @"HotUpdaterExample";
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = @{};
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [self bundleURL];
}
- (NSURL *)bundleURL
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
return [HotUpdater bundleURL];
#endif
}
@endVerifying the Setup
- Check your Firebase dashboard for the newly created firebase function.
- Test the HotUpdater integration in your React Native app.
You’re all set! 🎉 Start using hot-updater with Firebase for seamless updates in your React Native app.
This document simplifies the initialization process, making it easy for developers to get started with minimal friction.
AWS S3 Storage + Lambda@Edge Function
This guide walks you through setting up `hot-updater` with AWS S3 Storage and Lambda@Edge Function in a React Native project. You'll configure the environment, install required packages, and initialize AWS for seamless updates.
Overview
Build a custom backend server for Hot Updater database with any framework and ORM.