My experience building a multi variant app in React Native

Recently I faced a peculiar situation through a development process of a React Native app.

I thought it would be interesting to share my experience so it might be helpful for those like me who made tons of searches on the net looking for a light.

Our client needed to build an app for restaurants where we’d have a base project as a 'skin', so the structure is the same and all the apps are customized with their own settings(colors, logo, icons, keys …). The data is provided by an API Rest that takes the company_id to return the proper data for that variant, so that part is solved. As React Native works with native code, besides the JavaScript code we also have to deal with two native projects(Android/iOS) and for each of them we have specific settings (e.g. version, social keys, package name…) that should be dynamic.

The first and simple thought is to copy the project and customize it for that company. Pretty clean, totally independent projects with their own specific settings. But all of a sudden you may question yourself: what if we have hundreds of variants in the future and a bug is reported on the cart component for example. Certainly this is an important fix that has to be done for all variants of the app and turns out we have to make the same changes for ALL OF THEM. That would be a huge time consumer.

Ok, the second thought is to have the same project for all of them. So everything is concentrated on the same code and we have a configuration file to deal with the setting for each version. I came across several solutions related to this one but involving development and production versions. That is not my case but maybe it could work, so I took some time to check it out but turns out that I was blocked by the native codes. There is not a viable way to change the package name of the Android app for example, so do it manually every time I have to make a build or even debug the app is out of context. In the middle of this process I found the package react-native-config that helps you to create variables and use them in .plist files for example, maybe it could be useful for another project.

The thing is that despite the fact we have the same base project, in the end we have totally independent apps published in stores. So finally I decided to merge the previous solutions into only one. The answer was found by looking at what all the variants have in common: the JavaScript code!

Yes, that simple. And the keyword for the complete answer is Git.

We take all we need and put on control version, a configuration file was written to deal with the dynamic data. This file is specific for each project so this should not be under control version. I wrote a quick tutorial to get it a little bit clear.

We start by creating a new React Native project:

react-native init my-base-project

Once you have the project created, the first variant is built normally with all the features. After finishing the release of the first version of the app, if you need to create another variant for some other company you can just edit the .gitignore file adding the following lines:

#JS
/app.json
/ios_setup.js
src/RouterComponent.js
/package-lock.json
/package.json
/yarn.lock
/android-release.bundle.map
/ios-release.bundle.map
src/icon/
src/actions/types.js
NavBar.js
TabBar.js
ios/
android/

That will be the .gitignore file for all variants. The main idea is to deal only with the files that all projects have in common and can be managed dynamically through our configuration file that is types.js included on .gitignore.

#types.js
export const PRIMARY_COLOR = 'blue';
export const SECONDARY_COLOR = 'white';

At first it seems to be a bit strange because this files are included by default on control version, but this time they are not allowed in our control version due the fact they contain specific information about the app, so we cannot generalize for all variants. For example the /package.json generated by React Native and contains specific information for each project, so you shouldn’t change it unless you’re 100% sure of what you’re doing.

We left both native projects iOS and Android out of Git as we are not able to customize them dynamically through JS. I followed the same logic for all files in my project so in the end you have to choose which files will be kept under control version to make your life easier.

Once you have finished a feature that you were working on or a bug fix you simply push them to your repository and to work in another variant all you have to do is pull them. Easy-peasy!

I know that still doesn’t solve the problem of having to install another package, or having to edit something on native projects, like push notification configuration that, in my case, was made through native configuration because each variant has it’s own project, but I think that’s still an exception and for now it’s working pretty well for me. I’m still working with the limitations of React Native, but if you're facing a similar situation maybe could be a good solution for you as well.

Developer at Enhancers

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store