Managing Multiple Environments in React Native Android & IOS | Scripts for different Builds

Sathish K
7 min readJun 29, 2023

--

Generally, app environments can be divided into three main categories, with each their own unique purpose and functionalities: the development environment, the staging or testing environment and the production environment.

React-native-config allows you to set up different configuration files for different environments. This way, it can be used to store all your configuration variables in the same place so that you can access them from anywhere.

To create new React native project with all linting and auto commit formatting, check my story here.

https://medium.com/@sathishkcontact/create-react-native-project-from-scratch-with-new-architecture-basic-configuration-linting-b72c9c5f1975

Let’s follow the steps below to setup different env for react native projects.

Add react-native-config as dependency

yarn add react-native-config

2. Create .env files for all types required.

I have create for development, staging, production

Add App_Config Key in the env file.

Also update App.tsx to check env’s

/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
*/

import React from 'react';
import {
SafeAreaView,
StatusBar,
StyleSheet,
Text,
View,
useColorScheme,
} from 'react-native';
import config from 'react-native-config';
import AppColors from './src/AppColors';

const iStyles = StyleSheet.create({
screenContainer: {
flex: 1,
},
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
greetingContainer: {
borderColor: AppColors.green,
borderWidth: 1,
borderRadius: 10,
padding: 10,
alignItems: 'center',
},
font: {
fontWeight: '700',
},
greetingText: {
color: AppColors.black,
marginTop: 5,
},
});

function App(): JSX.Element {
const isDarkMode = useColorScheme() === 'dark';
const backgroundColor = isDarkMode ? 'black' : 'white';

const isFrom = config.APP_CONFIG ?? '';

return (
<SafeAreaView style={[iStyles.screenContainer, { backgroundColor }]}>
<StatusBar
barStyle={isDarkMode ? 'light-content' : 'dark-content'}
backgroundColor={backgroundColor}
/>
<View style={iStyles.container}>
<View style={iStyles.greetingContainer}>
<Text style={[iStyles.greetingText, iStyles.font]}>
Hi Sathish K,
</Text>
<Text style={[iStyles.greetingText, iStyles.font]}>
{`I am from ${isFrom}`}
</Text>
</View>
</View>
</SafeAreaView>
);
}

export default App;

3. add react-native-config dependency in android

open android>app>build.gradle and paste the code as below.

..........

apply from: project(':react-native-config').projectDir.getPath() + '/dotenv.gradle'

project.ext.envConfigFiles = [
development: ".env.development",
staging :".env.staging",
production:'.env.production'
]
.........

Also add resValue in default config as well.

android {

........

namespace 'com.reactnativesetup'
defaultConfig {
applicationId 'com.reactnativesetup'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
resValue 'string', 'build_config_package','com.reactnativesetup'

}

.........

}

Each env will multiple by 2 modes by default. Yes that is Debug, Release. We will see that in following steps.

4. Create FlavorDimensions and ProductFlavors in android app>build.gradle.

.......

android {

........

flavorDimensions 'env'
productFlavors {
development {
dimension 'env'
applicationIdSuffix ".development"
}
staging {
dimension 'env'
applicationIdSuffix ".staging"
}
production {
dimension 'env'
applicationIdSuffix ""
}
}
}

.............

👏 👏👏👏👏👏 we’ve completed different env setup for Android.

Let’s do for IOS

5. open the React Native IOS project in Xcode.

6. open Pods>Podfile and add react-native-config dependency in IOS as shown in image below.

.....

pod 'react-native-config/Extension', :path => '../node_modules/react-native-config'

........

7. Now Create scheme for different schemes.

In Xcode, select Product>Scheme>New Scheme. Select the project in dropdown and enter scheme name. And click ok to create the same.

8. In Xcode, select Product>Scheme>Edit Scheme.

select as development

Create 2 Pre-actions. To create env file inside ios folder and use the same. Select project in provide build settings drop down.Add below scripts and close.

Script 1:

rm "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}"
echo ".env.development" > /tmp/envfile

Script 2:

"${SRCROOT}/../node_modules/react-native-config/ios/ReactNativeConfig/BuildXCConfig.rb" "${SRCROOT}/.." "${SRCROOT}/tmp.xcconfig"

select as staging

Create 2 Pre-actions. To create env file inside ios folder and use the same. Select project in provide build settings drop down.Add below scripts and close.

Script 1:

rm "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}"
echo ".env.staging" > /tmp/envfile

Script 2:

"${SRCROOT}/../node_modules/react-native-config/ios/ReactNativeConfig/BuildXCConfig.rb" "${SRCROOT}/.." "${SRCROOT}/tmp.xcconfig"

select as production

Create 2 Pre-actions. To create env file inside ios folder and use the same. Select project in provide build settings drop down.Add below scripts and close.

Script 1:

rm "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}"
echo ".env.production" > /tmp/envfile

Script 2:

"${SRCROOT}/../node_modules/react-native-config/ios/ReactNativeConfig/BuildXCConfig.rb" "${SRCROOT}/.." "${SRCROOT}/tmp.xcconfig"

👏 👏 we’ve completed different env setup for IOS too.🥳 🎊 🎊 🎊 🎊 🎊

Now we will add scripts in package.json file to generate different builds.

aos -> Android operating system. ios -> iphone operating system

  "scripts": {

.........

"kn": "killall node",
"adb-r": "adb reverse tcp:8081 tcp:8081",
"tron": "adb reverse tcp:9090 tcp:9090",
"resetc": "yarn start -- --reset-cache",
"node:clean": "rm -rf node_modules&& yarn cache clean && yarn install",
"setDevelopment": "ENVFILE=.env.development",
"setStaging": "ENVFILE=.env.staging",
"setProduction": "ENVFILE=.env.production",
"ios:Pod:Reset": "cd ios && pod deintegrate && pod setup && pod install",
"ios:clean": "yarn node:clean && cd ios && rm -rf ~/Library/Caches/CocoaPods && rm -rf Pods && rm -rf ~/Library/Developer/Xcode/DerivedData/* && yarn ios:Pod:Reset",
"ios:Pod:install": "cd ios && pod install && cd ..",
"ios:bundle:assets": "react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios",
"ios:dev": "yarn setDevelopment react-native run-ios --mode=Debug --scheme \"development\"",
"ios:dev-release": "yarn ios:clean && yarn setDevelopment react-native run-ios --mode=Release --scheme \"development\"",
"ios:staging": "yarn setStaging react-native run-ios --mode=Debug --scheme \"staging\"",
"ios:staging-release": "yarn ios:clean && yarn setStaging react-native run-ios --mode=Release --scheme \"staging\"",
"ios:prod": "yarn setProduction react-native run-ios --mode=Debug --scheme \"production\"",
"ios:prod-release": " yarn ios:clean && yarn ios:bundle:assets && yarn setProduction react-native run-ios --mode=Release --scheme \"production\"",
"aos:clean": "yarn node:clean && cd android && ./gradlew clean",
"aos:bundle:assets": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res",
"aos:remove:assets": "rm -rf android/app/src/main/res/drawable-hdpi && rm -rf android/app/src/main/res/drawable-mdpi && rm -rf android/app/src/main/res/drawable-xhdpi && rm -rf android/app/src/main/res/drawable-xxhdpi && rm -rf android/app/src/main/res/drawable-xxxhdpi && rm -rf android/app/src/main/res/raw",
"aos:dev": "yarn setDevelopment react-native run-android --mode=developmentDebug --appIdSuffix=development",
"aos:dev-release": "yarn setDevelopment react-native run-android --mode=developmentRelease--appIdSuffix=development",
"aos:staging": "yarn setStaging react-native run-android --mode=stagingDebug --appIdSuffix=staging",
"aos:staging-release": "yarn setStaging react-native run-android --mode=stagingRelease --appIdSuffix=staging",
"aos:prod": "yarn setProduction react-native run-android --mode=productionDebug --appIdSuffix=production",
"aos:prod-release": "yarn setProduction react-native run-android --mode=productionRelease --appIdSuffix=production",
"aos:DD-apk": "yarn setDevelopment && yarn aos:clean && yarn aos:bundle:assets && yarn aos:remove:assets cd android && ./gradlew assembleDevelopmentDebug && killall -9 java",
"aos:DR-apk": "yarn setDevelopment && yarn aos:clean && yarn aos:bundle:assets && yarn aos:remove:assets cd android && ./gradlew assembleDevelopmentRelease && killall -9 java",
"aos:SD-apk": "yarn setStaging && yarn aos:clean && yarn aos:bundle:assets && yarn aos:remove:assets cd android && ./gradlew assembleStagingDebug && killall -9 java",
"aos:SR-apk": "yarn setStaging && yarn aos:clean && yarn aos:bundle:assets && yarn aos:remove:assets cd android && ./gradlew assembleStagingRelease && killall -9 java",
"aos:PD-apk": "yarn setProduction && yarn aos:clean && yarn aos:bundle:assets && yarn aos:remove:assets cd android && ./gradlew assembleProductionDebug && killall -9 java",
"aos:PR-apk": "yarn setProduction && yarn aos:clean && yarn aos:bundle:assets && yarn aos:remove:assets cd android && ./gradlew assembleProductionRelease && killall -9 java",
"aos:PR-Bundle": "yarn setProduction && yarn clean && yarn aos:bundle:assets && yarn aos:remove:assets && cd android && ./gradlew bundleProductionRelease && killall -9 java",
"open-apk": "open ./android/app/build/outputs/apk/",
"open-bundle": "open ./android/app/build/outputs/bundle/productionRelease",
"aos:dev-apk": "yarn aos:DD-apk && yarn open-apk",
"aos:dev:release-apk": "yarn aos:DR-apk && yarn open-apk",
"aos:staging-apk": "yarn aos:SD-apk && yarn open-apk",
"aos:staging:release-apk": "yarn aos:SR-apk && yarn open-apk",
"aos:prod-apk": "yarn aos:PD-apk && yarn open-apk",
"aos:prod:release-apk": "yarn aos:PR-apk && yarn open-apk",
"aos:bundle": "yarn aos:PR-Bundle && yarn open-bundle"
},

To run android app run this command in terminal.

yarn aos:dev

To create standalone apk and open the folder.

yarn aos:dev-apk

Follow respected scripts for the other environments.

To create bundle to upload playstore and open the folder.

yarn aos:bundle

To run ios app run this command in terminal.

yarn ios:dev

To create ipa file to upload appstore.

yarn ios:prod-release

Find app in the location which shown in terminal.

“/Users/”<Your_Username>”/Library/Developer/Xcode/DerivedData/”<Your_Filename> <generated code >/Build/Products/Release-iphonesimulator/”<Your_Filename>”.app

Go to the folder and compress app file and rename .zip as .ipa

Now ipa ready to uplaod App Store.

--

--