Sitemap

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

8 min readJun 14, 2020
Press enter or click to view image in full size
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
Press enter or click to view image in full size
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.

Press enter or click to view image in full size
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')
Press enter or click to view image in full size
android/settings.gradle

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

import com.lugg.ReactNativeConfig.ReactNativeConfigPackage;
Press enter or click to view image in full size
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')
Press enter or click to view image in full size
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

Press enter or click to view image in full size
.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"
Press enter or click to view image in full size
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.

Press enter or click to view image in full size
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"  }}
Press enter or click to view image in full size
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.

Press enter or click to view image in full size
Select create values XML File
Press enter or click to view image in full size
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>
Press enter or click to view image in full size
Add app_name tag after creating XML values file.

Do the same for staging and production:

Press enter or click to view image in full size
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",
Press enter or click to view image in full size
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:

Press enter or click to view image in full size
development environment
Press enter or click to view image in full size
staging environment
Press enter or click to view image in full size
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.

Press enter or click to view image in full size
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:

Press enter or click to view image in full size
Duplicate “Debug” configuration and name it “Development”
Press enter or click to view image in full size
Duplicate “Release” Configuration and name it “Release.Development”
Press enter or click to view image in full size
Development from “Debug” and Release.Development from “Release”

Create Debug and Release configurations for Staging:

Press enter or click to view image in full size
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…

Press enter or click to view image in full size
Edit Scheme

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

Press enter or click to view image in full size
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
Press enter or click to view image in full size
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”

Press enter or click to view image in full size
Change Build Configurations

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

echo ".env.staging" > /tmp/envfile
Press enter or click to view image in full size
New Run Script Action

Change Build Configurations for Staging as well.

Press enter or click to view image in full size
Build Configuration

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

echo ".env.production" > /tmp/envfile
Press enter or click to view image in full size
New Run Script Action

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

Press enter or click to view image in full size
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.

Press enter or click to view image in full size
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

Press enter or click to view image in full size
Change configurations Product Name

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

Change Info.plist for apply Bundle display name:

Press enter or click to view image in full size
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.

Press enter or click to view image in full size
podfile

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

Press enter or click to view image in full size
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.

Press enter or click to view image in full size
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;
Press enter or click to view image in full size
config.ts

Import { stage } property from App.tsx.

import {stage} from './config';

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

Press enter or click to view image in full size
App.tsx

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

Press enter or click to view image in full size
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

--

--

Responses (4)