Read Part 2 here!
Microservices architecture has become a well explored and beloved architecture in building large complex applications. Micro services allows the decomposition of a large monolith application into smaller loosely coupled entities that can leverage each other using http protocol. It is an implementation of the SOA architecture, and allows one to be able to leverage several advantages associated with building applications using this approach.
The advantages of loosely coupling components include,
I ventured to explore the ability to implement micro services architecture when building large complex mobile applications.
The idea was to bring the advantages of the micro services world to mobile application development.
Let us take for example the Alexa Mobile App. This single app is actually a fairly sophisticated and complex app, that provides a single portal for the user to interact with Alexa, and encapsulates several different functionalities, including IoT, VoIP call, music streaming and several others, all within a single complex mobile application.
While the single monolithic application approach may work well for simple mobile applications, surely there is a better way to build large complex mobile applications that have several different functional elements, using the micro services paradigm, thereby allowing for:
The first thought was to simply build a native mobile app using loosely coupled modules, that communicated with each other via well defined interfaces. However this was a far too simplistic an approach and would not really result in any of the aforementioned benefits of a micro services approach.
Mobile applications are different, complex and have their own unique features that need to be addressed.
The micro services solution would need to consider:
At the outset we explored a cross platform solution versus a native approach. Besides the obvious advantages of cross platform portability, in terms of code maintenance etc. we were also keenly aware of performance issues that were a frequent complaint of cross platform hybrid applications. To this end we deeply investigated the options of Cordova, Xamarin, Sencha, Ionic, and React Native.
Cordova simply wrapped the JS code and ran it within a web browser container. To that end the UI simply mimicked the native UI. Ionic libraries could be used for faster out of the box native UI mimicking. However both did not actually compile to native.
Xamarin and React Native were the two choices that complied to native. In that when you describe a button within your JS code in React Native, the RN bridge actually uses the native button component to render it within the specific app platform.
React Native in particular had the following features,
For this and other related reasons the choice of React Native as the cross platform framework for mobile application development was appealing.
It is important to remember that when thinking of cross platform the aim is not to achieve a 100% parity of shared codebase between multiple platforms. In reality about 90–95% of the codebase will be shared code base and cross platform, however there will still be a segment of code that will have to be customized for a particular platform (iOS, Android), to obtain performance efficiencies and leverage native platform capabilities.
After having narrowed down to React Native as the platform of choice for cross platform mobile app development, several questions came up,
Some of these questions related to RN ability to implement cross platform features, and interface with native code, all while preserving performance.
Performance
* What are the performance issues when using React Native?
* What are some common issues observed when using React Native?
* What are the most frequently used production libraries used in React Native?
Integration
* Can React Native work with existing native code? How does it integrate with native code? Can it integrate with both Objective C and Swift in iOS?
* Does React Native have enough third party API library and support?
* What is the future of React Native?
Other questions centered around features that are unique to mobile applications, and how these features would be implemented in React Native.
* What are the on-device data persistence options when using RN?
* How to handle user authentication, login and maintain persistent user session in ReactNative?
* How do push notifications (remote and local) work in React Native? How will push notifications work under the framework of mini-apps?
* How can we leverage Amazon Mobile Push SNS within React Native?
* What are the options for ReactNative Performance Monitoring Tool?
* What kind of unit testing and integration testing automation tools are available in RN?
Others related to implementing the micro services architecture within the RN framework,
Can we build React Native apps using micro services architecture?
The answer to this last question was crucial and opened another pandora’s box of questions.
* Can we build Mini Apps using React Native, with separate code repositories and separate compilations?
* What is the workflow when building the mobile app as combinations of mini apps?
While exploring the implementation of microservices in mobile applications i stumbled onto this interesting article by Walmart Labs.
The Walmart Labs team was looking for an effective solution and technology platform to migrate to and had chosen React Native as their choice of cross platform technology.
They introduced this concept of MiniApps which leveraged the Electrode Native platform and allowed developers to create small independent apps using React Native called “mini-apps”, that could focus on one particular functionality. Each Mini App could be compiled, run and tested separately and then a group of mini apps could be combined together into the Electrode Cauldron (similar to an npm file), and run within an Electrode Container. This allowed developers to combine the functionality of there different apps into a single integrated app. Whats more, mini apps can be integrated into native iOS or android without cumbersome interface logic, by simply importing it as an external library within xCode or Android Java.
A MiniApp is a React Native app, or more specifically a MiniApp is a JavaScript React native project representing a specific feature or component. It can be as simple as a single, simple UI component with minimal logic, or as complex as a multi-page application containing a complete application feature. Mini Apps can be combined together with other Mini Apps or native mobile components to build a full fledged, scalable and complex mobile application.
Besides the obvious cross-platform advantages of using React Native, Mini Apps built using Electrode Native open source libraries has the following added benefits.
Seamless ReactNative to MobileNative communication: Electrode Native provides mobile application developers a single third-party library known as the “Electrode Native Container”. The container includes all their MiniApps and developers interact with it as they would with any other third-party native library. If you need to update a MiniApp version or add new MiniApps to your container, all it takes is triggering a new container generation and publication. Developers only need to update the container version that is to be used within their mobile application. Thus, you simply add the container as a new native dependency to the native mobile application, as any other native third-party dependency, and the Electrode Native container does the heavy lifting of generating all the integration code. The Electrode Native container does this by packaging your React Native app into an AAR (Android) or framework (iOS), depending on the platform.
Data persistence is holding onto data in case the application or device is reset. Native iOS apps store on-device using CoreData or SQLite, and Native Android apps also have a SQLite implementation. In React Native the out-of-the-box option for on-device storage and data persistence is AsyncStorage.
**AsyncStorage**AsyncStorage is a simple, unencrypted, asynchronous, persistent, key-value storage system that is global to the app.
On iOS, AsyncStorage is backed by native code that stores small values in a serialized dictionary and larger values in separate files.
On Android, AsyncStorage will use either RocksDB or SQLite based on what is available. AsyncStorage has a default limit of 6MB on Android. It is possible to configure a larger limit (on Java code) or use redux-persist-filesystem-storage as storage engine for Android.
Storage stays local to the device, is unencrypted, goes away if you delete the app and persists during upgrades (both native upgrades ala TestFlight and code upgrades via CodePush).
The downside to AsyncStorage is that it has slow runtime and has no indexing capabilities. Because AsyncStorage only accepts string as its value, all data must first be serialized into string before being inserted, and deserialized once retrieved.
AsyncStorage is not suited when dealing with a large amount of data.
Realm Database**Realm** is a relative new comer in the on-device data persistence option. It is an object-database management system, with first stable release in January 2017. Like SQLite, Realm is serverless and cross-platform. It can be stored both on disk as well as in memory. It is highly versatile with cross-platform support for iOS, Android, Xamarin, ReactNative and UWP (May 2017).
Realm Database is an alternative to SQLite and Core Data, is faster than AsyncStorage and SQLite, and has several other advantages including,
In order to maximize the performance, Realm has statically typed database which means you first need to define the structure of database (using JS classes) before you can add/remove anything to it.
Realm React Native’s API allows you to write your app once in JavaScript and target both iOS & Android, but the Realm file format is also completely cross-platform, allowing data to be shared across iOS & Android easily.
When dealing with a large amount of data, or simply require a faster local storage, Realm is a better and more attractive option.
Most of the material in this section is sourced from various articles, websites and forums on the subject, and is meant to abstract some of the common and frequently encountered real world issues observed by teams using RN.
I came across the following video where Tal Kol(Wix.com) provides a smart approach to overcoming the performance limitations of React Native.
He first examines why React Native is faster than say cordova or phone gap bridge that does exactly the same thing, and passes data between the JS world and the Native world. He concludes that
He advocates keeping the passes over the bridge to a minimum, since it is not the JS realm that is slow, or native that is slow, it is the changing from the JS to the native, the bridge is the factor to slow it down
While React Native does have some fantastic selling points and does a good job bridging the gap between iOS and Android, you’re not going to achieve complete parity between the two operating systems. There are certain things that one platform can do that the other can’t handle, mostly related to styling views, but also more important considerations such as performance testing.
There are some inconsistencies between the functionality of React Native on iOS and on Android. Some React Native behaviors and style implementation differ between the platforms. Some properties are supported on iOS but not Android and iOS seems to have more features than Android. In the React Native documentation you can see these properties and features marked as “Android only” or “iOS only.”
Like any cross-platform abstraction, React Native can be leaky. To write a cross-platform app that purely lives inside JS Runtime, you have to write React-only code. React and React Native doesn’t have ways to handle primitives like UINavigationController — they want your entire app to be represented as a series of components that can be mapped across many platforms.
Read Part 2 here
In part 2 of this article we will delve into push notifications, MBaaS options, and explore how React Native interfaces with existing native code using Native Modules. We shall the tie all of these pieces together in concluding remarks and will present a holistic proposed implementation of microservices architecture using mini apps, MBaaS, push notification services, realm database, and electrode native container.
Found this post useful? Hit the 👏 button below to show how much you liked it :)
Follow me on Medium for the latest updates and posts!
Read Next: The Microservices Approach to Mobile Application Development (Part 2)
Other Articles: