The missing guide to React Native app variants — Part 1

Tamás Menyhárt
Supercharge's Digital Product Guide

--

Introduction

Cross-platform mobile app development has really improved over the years and it became a viable alternative to native app development for small and mid-sized businesses. React Native, one of the first mobile frameworks out there is still in demand, thanks to its great community and beginner-friendly documentation.

Although React Native is relatively easy to start with for Javascript developers, the official documentation is missing some general use cases. One of these is the possibility to create different variants of an app, and be able to install all of these app variants on the same device. This use case needs a native Android/iOS code setup, which could be scary for Javascript developers. But don’t worry: stay with me and I’ll show you how to set up your React Native app to support app variants, leading you through the Android/iOS setup step by step.

React Native vs. app variants: an article series to fill those missing gaps

Since there are a bunch of topics we need to cover here, I want to dedicate a series of three articles to explain how to support app variants in React Native in detail.

Here’s an overview of the series:

In the first part we’ll create an app called FruitApp with QA and PROD environment based variants, and set unique package name/bundle id for them, which will make it possible to install the app variants on the same device (in Android/iOS the package name/bundle id must be unique for every app, it’s like on the web that multiple sites can’t have the same URL).
As an example, the environment-related builds can be used to use different base URL for the network requests
(test data in QA environment app build, production data in PROD environment app build).

In the second part, we’ll add the APPLE and BANANA flavor based variants, and set unique package name/bundle id, app name and app icon for them.
As an example, the flavor related builds can be used to implement some business logic differently or style the apps differently (red primary color in APPLE flavor app build, yellow primary color in BANANA flavor app build).

In the third part, we’ll add React Native Config as a dependency. The main purpose of this library is to help us to keep the environment/flavor related constants in plain .env files and be able to read the values in our Javascript codebase. The specific .env files can be injected to the apps during CI build processes too.

In the end of the series we’ll have the following 4 app variants for both platforms (Android/IOS) with different package name/bundle id, app name and app icon:
- FruitApp-APPLE-QA, FruitApp-APPLE-PROD
- FruitApp-BANANA-QA, FruitApp-BANANA-PROD

Getting started

As a first step, let’s initialize the React Native app using the React Native CLI:
npx react-native init FruitApp --template react-native-template-typescript --npm

Checking Android default package name

After the project has initialized, we should look for the “applicationId” key in the “android/app/build.gradle” file under the “defaultConfig” block to check our initial package name on Android:

android {
defaultConfig {
applicationId "com.fruitapp"
}
}

Checking iOS default bundle id

In the case of iOS, first, we should open the iOS project file:
cd ios && open FruitApp.xcworkspace , and we need to navigate according to the following :

  • In the Project sidebar (on the left), select the “FruitApp” project
  • In the “Project/Targets” pane, select “FruitApp” under the “Targets” block
  • Finally, select the “General” tab (in the middle), and we can check the default bundle id on iOS next to the “Bundle Identifier” key.

At the moment of writing in a generated React Native project the default package name/bundle id is not matching, so we should update the iOS bundle id to “com.fruitapp” to keep the app id consistent across platforms.

Xcode, project bundle id modification
Xcode, project bundle id modification

Creating environment based app variants

As I’ve mentioned in the article series part, in this step we will create app variants based on the environment. As the Android part of this setup is easier, let’s start with that.

Creating Android environment based app variants

First, we should open the “android/app/build.gradle” file, and look for the “buildTypes” block. We should define our available flavor dimensions below this block then match every product flavor we want with a flavor dimension within the “productFlavors” block:

android {
buildTypes {
debug {
...
}
release {
...
}
}
flavorDimensions ("environment")
productFlavors {
qa {
dimension "environment"
applicationIdSuffix ".qa"
}
prod {
dimension "environment"
}
}
}
Android Studio, app gradle file modifications
Android Studio, environment based product flavors

After the above modification is done, we should update our scripts to be able to run and build the environment based app variants from the command line. For this let’s open up the “package.json” file and update the scripts section:

{
"scripts": {
"run:android:qa": "react-native run-android --variant=QaDebug --appIdSuffix=qa",
"run:android:prod": "react-native run-android --variant=ProdDebug",
"build:android:qa:release": "cd android && ./gradlew assembleQaRelease",
"build:android:prod:release": "cd android && ./gradlew assembleProdRelease"
}
}
Visual Studio Code, android run and build scripts
Visual Studio Code, android environment based run and build scripts

Using the above scripts, we can install both the QA and PROD app variants on the same device. The QA app will have the “com.fruitapp.qa” package name, and the PROD app will have the “com.fruitapp” package name.

Creating iOS environment based app variants

In the case of iOS, first, we need to create configurations for each build type (debug, release) and environment (QA, PROD) pair. After that, we need to create schemes for each environment (QA, PROD) and pair the schemes with the correct configurations.

Creating iOS configurations

To view the current configurations in Xcode, we need to navigate according to the following :

  • In the Project sidebar (on the left), select the “FruitApp” project
  • In the “Project/Targets” pane, select “FruitApp” under the “Project” block
  • Finally, select the “Info” tab (in the middle), and we can check the configurations under the “Configurations” block.
Xcode, existing configurations
Xcode, existing configurations

To create new configurations, we need to duplicate the existing “Debug” and “Release” ones for every environments (QA, PROD). Duplicating a configuration is as easy as clicking on the small “+” icon below the list of configurations, and selecting the “Duplicate configuration” option.

We should duplicate “Debug” to create the “Qa.Debug” and “Prod.Debug” configurations, and we should duplicate “Release” to create the “Qa.Release” and “Prod.Release” configurations.

Xcode, environment based configurations
Xcode, environment based configurations

Creating iOS schemes

To view the available schemes, we need to navigate to the “Manage Schemes” dialog by using the “Product / Schemes / Manage Schemes…” menu.

Xcode, manage schemes menu
Xcode, manage schemes menu
Xcode, manage schemes dialog
Xcode, manage schemes dialogue

In this step, we need to duplicate the existing “FruitApp” scheme (note that we need to do it twice, one for the “Qa.FruitApp” scheme and one for the “Prod.FruitApp” scheme).
To create a new scheme, the following steps should be followed:

  • Below the scheme list, click on the small “gear” icon and select the “Duplicate” option
  • Give a name to the scheme (at the top)
  • Tick the “Shared” checkbox (at the bottom)
Xcode, QA scheme details
Xcode, QA scheme details

Additionally, the following steps should be followed within the create scheme dialogue to pair a scheme with a configuration:

  • On the left pane, select the “Run” item, and change to the “Build configuration” dropdown value to the related debug configuration (Qa.FruitApp scheme — Qa.Debug configuration, Prod.FruitApp scheme — Prod.Debug configuration)
  • On the left pane, select the “Test” item, and change to the “Build configuration” dropdown value to the related debug configuration (Qa.FruitApp scheme — Qa.Debug configuration, Prod.FruitApp scheme — Prod.Debug configuration)
  • On the left pane, select the “Analyze” item, and change to the “Build configuration” dropdown value to the related debug configuration (Qa.FruitApp scheme — Qa.Debug configuration, Prod.FruitApp scheme — Prod.Debug configuration)
  • On the left pane, select the “Profile” item, and change to the “Build configuration” dropdown value to the related release configuration (Qa.FruitApp scheme — Qa.Release configuration, Prod.FruitApp scheme — Prod.Release configuration)
  • On the left pane, select the “Archive” item, and change to the “Build configuration” dropdown value to the related release configuration (Qa.FruitApp scheme — Qa.Release configuration, Prod.FruitApp scheme — Prod.Release configuration)
Xcode, created environment based schemes
Xcode, created environment based schemes

Setting iOS configuration bundle ids

As a final step, we need to update the bundle ids for the “Qa” configurations. To update the configuration bundle ids in Xcode, we need to navigate according to the following:

  • In the Project sidebar (on the left), select the “FruitApp” project
  • In the “Project/Targets” pane, select “FruitApp” under the “Targets” block
  • Select the “Build Settings” tab (in the middle), and we can check the configuration bundle ids under the “Packaging” block by opening the “Product Bundle Identifier” item
  • Update the bundle id for the “Qa.Debug” and “Qa.Release” configurations to “com.fruitapp.qa”
Xcode, QA environment configuration updated bundle ids
Xcode, QA environment configuration updated bundle ids

After the above modification is done, we should update our scripts to be able to run and build the environment based app variants from the command line. For this let’s open up the “package.json” file and update the scripts section:

{
"scripts": {
"run:ios:qa": "react-native run-ios --scheme Qa.FruitApp --configuration Qa.Debug",
"run:ios:prod": "react-native run-ios --scheme Prod.FruitApp --configuration Prod.Debug",
"build:ios:qa:release": "cd ios && xcodebuild -scheme Qa.FruitApp build",
"build:ios:prod:release": "cd ios && xcodebuild -scheme Prod.FruitApp build"
}
}
Visual Studio Code, android run and build scripts
Visual Studio Code, ios environment based run and build scripts

Using the above scripts, we can install both the QA and PROD app variants on the same device. The QA app will have the “com.fruitapp.qa” bundle id, and the PROD app will have the “com.fruitapp” bundle id.

Note that to build the iOS app, the signing of the app needs to be done, but signing an app is not part of the article series.

Closing thoughts

I hope that the first part of the article series was useful and made you interested in the upcoming parts. If you’re more into checking code directly, you can find the example app on Github which will drive you through the article series steps commit-by-commit.

See you soon, take care.

At Supercharge, we are a next-generation innovation agency working with our clients to create transformative digital solutions. If you liked this article, check out some of Supercharge’s other articles on our blog, or follow us on LinkedIn, and Facebook. If you’re interested in open positions, follow this link.

--

--