How to manage staging and production env for React Native App

Sokserey PHON
4 min readSep 12, 2019

In this blog will demonstrate you guys how to manage your React Native App with different env, staging and production. This help me a lot when I want to change my environment to debug or release my app to the Store.

First thing first, we are going to use one of config file library, react-native-config. After following the docs, if you are using podfile you will face the following error:

/node_modules/react-native-config/ios/ReactNativeConfig/ReactNativeConfig.m:2:9: fatal error: ‘GeneratedDotEnv.m’ file not found

To solve it just open your podfile, then at the bottom of your podfile please add the following codes and then run pod install:

post_install do |installer|installer.pods_project.targets.each do |target|if target.name == “React”target.remove_from_projectendif target.name == ‘react-native-config’phase = target.project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)phase.shell_script = “cd ../../”\“ && RNC_ROOT=./node_modules/react-native-config/”\“ && export SYMROOT=$RNC_ROOT/ios/ReactNativeConfig”\“ && export BUILD_DIR=$RNC_ROOT/ios/ReactNativeConfig”\“ && ruby $RNC_ROOT/ios/ReactNativeConfig/BuildDotenvConfig.ruby”target.build_phases << phasetarget.build_phases.move(phase,0)endendend

Next, I am going to create 3 files in my root project

// .env
API_HOST=https://api.staging.foobar.com

// .env.staging
API_HOST=https://api.staging.foobar.com

// .env.production
API_HOST=https://api.foobar.com

Note: please follow the above convention, no space needed

Now, to put those vars to use for my React Native app, here’s how my config file usually looks like:

// import wherever you want to use your config vars

import env from 'react-native-config'
const API_HOST = config.API_HOST;

That’s all. By default, react-native-config reads from the .env file, but reading from any file & running the project is possible via the following command:

$ ENVFILE=.env.staging react-native run-ios

All good so far, but I want my build process to be as automated as possible. So manually specifying the .env file is not acceptable. Avoiding this is what we're going to do next.

IOS SETUP

On iOS, I’m going to take advantage of the concept of schemes.

go to your XCODE -> PRODUCT -> EDITSCHEMA -> DUPLICATESCHEMA

After duplicating schema I am going to create another new schemas, naming is very important as my default schema is pick_up so I am going to create another two schemas called pick_up.staging and pick_up.production

Next to ensure that my schema loads up .env file I want, I am going to select my pick_up.staging schema and then expand run section -> click on Pre-action -> click on + button and then choose New Run Script Action and add the following script

echo “.env.staging” > /tmp/envfile

for pick_up.production we are going to do the same step as pick_up.staging by just selecting pick_up.production and add the following script

echo “.env.production” > /tmp/envfile

Note: When you want to change your environment, you just select your schema (staging or production) and then build. However, when you first build, sometimes, It won’t change your environment yet so you need to do it twice and to ensure that just console.log(your config var).

That is the end of IOS setup let move to another funny setup for Android

ANDROID SETUP

For Android, we have build types. So in your android/app/build.gradle, under apply plugin: “com.android.application" please add

project.ext.envConfigFiles = [
debug: ".env",
release: ".env.production"
]
apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

To run the app using one of the build types defined above, go to View -> Tool Windows -> Build Variants and select the variant (in the newly exposed window) before building:

Finally we completed all steps for both IOS and Android. For your sensitive key please do not commit to your repository, eg(.env.staging and .env.production).

--

--

Sokserey PHON

Just a young dumb dude who loves programming. Senior Mobile Developer (Flutter/React Native)