Multi Environments Distribution with React Native using Azure AppCenter Part.1 Configuring react-native-config

Hyunwoo Sung
8 min readJun 14, 2020
Display name for each configuration

Starting next month, we are planning to start implementing our very first mobile app with ReactNative, but none of us had a good experience with Native app distribution on Apple app store or Google play store. So I went ahead and tried some deployment and distribution scenarios. There are some requirements that I wanted to achieve:

  • Local debug environment for each stage
  • .env configuration should not uploaded on repository
  • Auto distribution with git commit(pull request)
  • Code push
  • Works for both iOS and Android
  • App display name should be different for each environment.

There are many great tutorials on what I want to achieve, but I had to open up so many browsers and switching here and there to finally make the goal. So I decided to write this article to summarize what I found and experienced.

This tutorial contains a lot of screenshots, so if you get bored during the tutorial and just want the code, please go ahead and check out this github repository :D

Init react native project

In this article, we will start with typescript template.

npx react-native init rn_multi_env --template react-native-template-typescript

Try run both iOS and Android by:

npm run ios

or

npm run android
iOS and Android simulator

Now we are ready to add our packages for multi environments.

Install react-native-config

We are going to use react-native-config package. This package is little bit difficult to configure, but it does what it supposed to do.

Install the package:

npm install react-native-config --save

Link the library for RN < 0.60:
Use below command if your React Native version is below 0.60.

react-native link react-native-config

Once you link the library, below files will be modified:

settings.gradle, MainApplication.java for android.

Podfile for iOS.

After linking the library

Link the library for RN > 0.60:

Follow next guide if your React Native version is above 0.60.

Add below lines to android/settings.gradle

include ':react-native-config'project(':react-native-config').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-config/android')
android/settings.gradle

Add below line to android/app/src/main/java/com/{MyProject}/MainApplication.java

import com.lugg.ReactNativeConfig.ReactNativeConfigPackage;
android/app/src/main/java/com/{MyProject}/MainApplication.java

Add below line to android/app/build.gradle

//link react-native-configimplementation project(':react-native-config')
android/app/build.gradle

Now we are going to create files that have our environment variables. development, staging, production.

In .env.development:

stage=development

In .env.staging:

stage=staging

In .env.production

stage=production

Make sure you add these files in .gitignore

.gitignore

We will skip iOS link since this guide is based on RN version > 0.60 and by default all you have to do is

cd ios & pod install

If you need detailed instruction on manual link iOS, lease refer Setup section of react-native-config

Android Configurations

We will use product flavors to distinguish our environments.

Add below lines to android/app/build.gradle

project.ext.envConfigFiles = [  dev: ".env.development",  stg: ".env.stating",  prd: ".env.production"]apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
android/app/build.gradle

In order to support different build variants(ex: development, staging, product), add below line as well. Refer to Advanced Android Setup for more detail.

defaultConfig {
...
resValue "string", "build_config_package", "com.rn_multi_env"
}

Note that “com.rn_multi_env” is your package name from AndroidManifest.xml <manifest package=“…”> tag.

AndroidManifest.xml and build.gradle

Add product flavors:

Using flavorDemensions property, we will create “default” flavor dimension to group “dev”, “stg” and “prd” product flavors.

flavorDimensions "default"productFlavors {  dev {    dimension "default"    applicationIdSuffix ".dev"    versionNameSuffix "-dev"  }  stg {    dimension "default"    applicationIdSuffix ".stg"    versionNameSuffix "-stg"  }  prd {    dimension "default"    applicationIdSuffix ".prd"    versionNameSuffix "-prd"  }}
Product flavors in build.gradle

Create source sets:

When you create a new build variant, you need to add equivalent source sets under {MyProject}/app/src.

You can manually create these source sets or use android studio to create them.

1. Open the Project pane and select the Project view from the drop-down menu at the top of the pane.

2. Navigate to MyProject/app/src/.

3. Right-click the src directory and select New > XML > Values XML File.

4. Enter the name for the XML file or keep the default name.

5. From the drop-down next to Target Source Set.

6. Type strings.xml for Values File Name.

7. Click Finish.

Select create values XML File
Create strings.xml source set with “dev” Target Source Set

Now we need to add below line to newly created strings.xml inside <resource>…</resource> tag

<string name="app_name">rn_multi_env.dev</string>
Add app_name tag after creating XML values file.

Do the same for staging and production:

Add app_name tag after creating XML values file.

Add run scripts to package.json:

"android:dev": "react-native run-android --variant=devDebug --appIdSuffix=dev","android:stg": "react-native run-android --variant=stgDebug --appIdSuffix=stg","android": "react-native run-android --variant=prdDebug",
package.json

Run the script for dev environment:

npm run android:dev

Run the script for stg environment:

npm run android:stg

Run the script for prd environment:

npm run android

Check out App info to see app name has changed according to our strings.xml:

development environment
staging environment
production environment

iOS Configurations

We will start iOS configuration with adding new configurations and schemes to support multi environments.

Add build configurations and schemes:

Start Xcode and open project’s ios workspace({ProjectFolder}/ios).

Select your project in Project navigator, and select your project under PROJECT again.

Project Info tab

Search for Configurations and locate+ button. We will create total 6 configurations here.

Because our final goal is to have multiple environments and each stage will have debug and release configuration, we will create both Debug and Release configuration for each stage.

Create Debug and Release configurations for Development:

Duplicate “Debug” configuration and name it “Development”
Duplicate “Release” Configuration and name it “Release.Development”
Development from “Debug” and Release.Development from “Release”

Create Debug and Release configurations for Staging:

Build Configurations for Staging

Skip for the Production Configurations as we will use “Debug” and “Release” for production configuration.

So now we have total 6 configurations.

“Development” for development debug

“Release.Development” for development release

“Staging” for staging debug

“Release.Staging” for staging release

“Debug” for production debug(Default)

“Release” for production release(Default)

Add schemes:

Click on current scheme and select Edit Scheme…

Edit Scheme

Duplicate scheme from “{ProejctName}” and name it {ProjectName}.dev

Duplicate scheme from “Debug” and name it {ProjectName}.dev

Expand “Build” settings on left panel and click “Pre-actions”, then select “New Run Script Action” from + sign at the bottom.

Add below line to apply .env.development to build environment.

echo ".env.development" > /tmp/envfile
New Run Script Action

Change configurations of “Run”, “Test”, and “Analyze” from “Debug” to “Development”

Change configurations of “Profile” and “Archive” from Release to “Release.Development”

Change Build Configurations

Duplicate scheme for Staging and add Pre-actions script as below.

echo ".env.staging" > /tmp/envfile
New Run Script Action

Change Build Configurations for Staging as well.

Build Configuration

No need to change Build Configurations for {ProjectNmae} scheme except Pre-actions script as below.

echo ".env.production" > /tmp/envfile
New Run Script Action

Click Manage Schemes… button and enable “Shared” check box for all schemes.

Manage Scheme

Different Product Name and Identifier:

Now we need to give proper Bundle Identifier and Product Name for each configurations.

Select project Target from TARGETS panel and in the Build Settings tab, search for Product Name under Packaging category.

Product Name in Build Settings tab

For both Development and Release.Development, change the value as {ProjectName}.dev

Do the same for Staging and Release.Staging {ProjectName}.stg

Change configurations Product Name

Note that Product Bundle Identifier also changed according to Product Name.

Change Info.plist for apply Bundle display name:

change {ProjectName} to $(PRODUCT_NAME)

Ok we are done with xcode now. Let’s go back to vscode and change our podfile.

Open up Podfile under {ProjectFoler}/ios and insert below lines.

platform :ios, '9.0'require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
// add below lines
project 'rn-multi-env','Development' => :debug,'Development.Release' => :release,'Staging' => :debug,'Staging.Release' => :release

Locate all the occurrence of ‘Debug’ under flipper configurations.

podfile

Change this to array of debug configuration: [‘Development’, ‘Staging’, ‘Debug’]

change ‘Debug’ to [‘Development’, ‘Staging’, ‘Debug’]

Change directory to {MyProject}/ios and install pod:

(cd ios; pod install)

Add below scripts to package.json

"ios:dev": "react-native run-ios --configuration Development --scheme rn_multi_env.dev","ios:stg": "react-native run-ios --configuration Staging --scheme rn_multi_env.stg","ios": "react-native run-ios --configuration Production --scheme rn_multi_env",

Run each script to see the Product name.

Display name for each configuration

Testing environment variable

Now we have to verify if our .env variables are properly applied to each configuration.

Create config.ts file at the project’s root and add below lines.

import env from 'react-native-config';export const {stage} = env;
config.ts

Import { stage } property from App.tsx.

import {stage} from './config';

Add below line inside<View>…</View> tag.

App.tsx

Run each script and verify if the environment variables are properly applied.

Run with each configuration.

That’s all from configuring multi environments with react-native-config.

I have uploaded this tutorial on my github repository. So feel free to drop by and try it out.

I will comeback with Part.2 Configuring AppCenter next week.

Thanks for reading:D

--

--