How to setup multiple environments in React Native

Emilio Heinzmann
CWI Software
Published in
7 min readSep 8, 2020
Photo by Ryan Ancill Shulman from Unsplash

In this article I’ll explain a bit more about how to setup different environments in React Native and how to properly manage them across Javascript and native code.

To fully understand it you need to have knowledge in Javascript, React Native and understand a bit about React Native’s project native structure (iOS and Android). So… let’s start.

Motivation

That article is like a puzzle I grouped all the important and valuable information that I’ve found during the implementation of environment setup in a project. Most of the articles or tutorials that I could find about the theme did not approach both, Javascript and Native code. So, I decided to do it.

I will be happy if it helps you in any aspect 😄.

Understanding the problem

In a real project, we usually have three main environments (Development, Staging and Release). Those have each a different environment setup, like different API urls or Firebase projects.

But, how can we properly setup these variables according to the type of App that we want to run?

Since we usually have a lot of configurations that depend on which environment we are running, all of you agree that changing them by hand is not a good idea, right? In that case, we need to write some scripts to automate it, in both JS and Native sides. And that is exactly what we are going to see during this article.

Setting up Javascript Environment

Now that we know the problem, we can start to solve it. First, we need to setup different environments for the Javascript side of our project. That step is a bit easier and straight forward, since we just need to create some files and write a script to replace them before running the application.

First of all, we need to create the folders and files structure. In our project src path, create a config folder with another folder called env inside it. For each of the environment types that we have in our application we need to create a folder under the env directory. The final structure will be something like that:

Example of file tree for JS env

Each of the folders will have its own index.js file, like in the example bellow:

Note: I like to work with that type of structure folder/index.js, but, feel free to modify it according to your project, and keep in mind that this will affect the code that you need to write in the following steps.

The environment structure of our project for the Javasript side is created. But we need a way to run our application using each of these configurations. To do so, we can write a script that replaces export { env } from './debug' inside the config/env file with the right environment export string.

To validate the params of our node script we are going to install yargs library: yarn add -D yargs

Then, we are able to create the following script that will replace the line mentioned above and make it possible to choose what environment we want to run. The most important parts are commented with the explanation. Please, take a look:

Script to replace JS environment.

Usually I place that file inside the scripts folder on the root of my project (where I also have other scripts to automate other parts of my building process).

We have already created the folders structure and the script that will replace everything, now we just need to run it before react-native run-android or react-native run-ios to make sure that the right environment is being used during the process. To do so, you can create some scripts inside package.json:

To run your project, instead of using run-android or run-ios you should use the scripts that we have created. For example, if I want to run my android app with debug environment, I am going to use yarn run:android:debug.

For Javascript side that would be all. Now you just need to add the variables, like API Url, in each env object and use it in your application.

Setting up Native Environment

As you may know, when working with React Native, some libraries or implementations need both Javascript and Native configuration. Examples of that are Facebook SDK and Firebase. To manage these different configurations on native side, we are going to work with build types for Android and with build configurations for iOS.

Setting up Android Environment

First of all, inside android/app/build.gradle under buildTypes we need to add a new buildType called staging. It will look like that:

Don’t forget to add matchingFallbacks there, without it the build may fail. If you want, you can read more about it here.

Now we need to do some extra configuration to allow the staging build type to work properly. Inside the project.ext.react array add the following configuration:

That’s necessary because, by default, React Native enables development mode and doesn’t bundles Javascript in non default buildTypes.

To finish, we need to create a new folder called staging under android/app/src and add a new AndroidManifest.xml file (you can copy the one that’s already created inside the debug folder).

Inside that folder you can add all configurations that are necessary for the staging buildType.

That’s the way Android knows what the configurations that are going to be used to build your app are. It will look inside the folder with same name as the buildType, and, after that, use the main folder configuration.

Let’s say you want to have different app names for each buildType. You can do it by adding a new strings file and overwriting the app_name string. That works with Firebase’s google-service.json file too, just add the file under each folder and it will work fine.

Note: Don’t forget to properly follow the folders structure. For example, the original strings file is located under main/res/values, so if you want to overwrite it on staging build, you need to create the same directories tree under staging folder.

Setting up iOS Environment

For iOS the logic is almost the same, but with some little differences. Let’s dive into 😜?

  • Open the project in XCode and duplicate the Release build configuration naming it with Staging.
  • Under our iOS project folder, we are going to create a new folder called ConfigFiles and add three .xcconfig files, one for each build configuration. Let’s use the same example that I have used for Android. To have a different app name for each build configuration you can add a new property to each file.
  • To have access to these properties in your application you need to load them inside each build configuration. We can do that by simply adding it as a ConfigFile on project level.

But how can I use these properties that were loaded into my application?

Just go to your Info.plist file and replace whatever you want with the properties. Following the example, I will replace my old Bundle display name with the variable APP_DISPLAY_NAME.

Ok… But that just allow us to load different properties and not different files for each build configuration. In case of Firebase, that has a different GoogleService-Info.plist file for each of the configurations, we need to have a different approach. To do that, we can run a script at build time that verifies what is the current build configuration that we are using and replace the necessary files.

I am currently using the following script to do that work for me:

font: https://medium.com/rocket-fuel/using-multiple-firebase-environments-in-ios-12b204cfa6c0

Basically, it searches for the GoogleService-Info.plist files inside my ConfigFiles folder, and replaces it according to the current build configuration.

The most important sections of this script are commented. It was created to replace the Firebase’s GoogleService-Info.plist file, but it can easily be modified to replace other files too.

To run this script, we need to add it to our target Build Phases as a new Run Script Phase:

Last but not least, we need to add the GoogleService-Info.plist files under our ConfigFiles directory to allow our script to run properly.

If you have other files that need to be replaced, you can add them in this directory tree too, just don’t forget to modify the current script or create a new one to replace these files.

That’s all folks 🚀

Now, just like magic, you can properly manage multiple environments in your React Native project without thousands of lines of configuration. Just run your project using one of the created scripts and everything will work fine.

If you have any questions or suggestions, please leave a comment. I would be glad in hearing you.

I would like you to check out some other articles about this theme that helped me to write this one:

Thanks for reading!

--

--

Emilio Heinzmann
CWI Software

Estudante de Ciência da Computação na Unisinos e Desenvolvedor React Native na CWI Software.