At 3angleTech, we do not shy away from trying new platforms when we develop the products that our customers need. We have experience with native apps, but we are also open to using new platforms. This helps us remain relevant, both as individual software developers and as a company. One day, a customer wanted us to develop a subscription-based podcast-like mobile app that could help users learn a foreign language. The plan was to use it to deliver original audio content that was a mix between entertainment and education, in multiple languages, to an international audience. One possible approach was to develop two separate native apps for Android and iOS, with the same features. However, for this project, more than for others, we were constrained by time, money, and maintenance costs. That’s why we decided to try a different approach and dip our toes into React Native. Here’s how it went and what we learned from it.
Our goal was to develop a Minimum Viable Product (MVP) as fast as possible, with a minimum of work, so that we could test our customer’s ideas. We did not want to invest into developing native apps for both Android and iOS, because it would have meant doing the same work twice and having to solve the different bugs and issues specific to each mobile platform. We wanted to use a platform that offers support for one codebase to build the app for both Android and iOS. We analyzed the following options:
We decided to use React Native because we could also enroll our web developers on this project and provide an app with a “close to native” mobile experience. The promise of React Native seemed very exciting and exactly what we needed for this project.
We started our work by studying the documentation for React Native, and we were thrilled to find useful step-by-step guides and explanations in it. The “Getting Started” section led us to the Expo software development kit. We immediately installed the Expo app from the Play Store and the App Store, so that we could use it during the development process. At this point, we weren’t exactly sure how it would be used, but we knew we would figure it out. 🙂
We wrote our Hello World code, and wanted to build it, so that we could see it run. But hey, the documentation told us to scan a QR code from the terminal, with Expo, and the project will run?!? What kind of sorcery is this? It’s nice, in a weird way, but it doesn’t feel like software engineering. Scanning QR codes, really?
We found out later that, in Expo, there is also a build option available from the console. Still, the documentation did not promote it, probably to make things friendlier for beginners.
We decided to adapt and continue with our work. We started the development process, and figured out what libraries and components we needed. During this process, we learned that ExpoKit is the library that provides support for the native functionality we required: audio playback support, storage, native widgets, notifications, etc.
We arrived at the point when we wanted to build the app and share it with others by publishing it somewhere. We noticed that the package size was huge for a couple of static pages (around 20 MB), which is a lot for a mobile app in an MVP stage. We decided to ignore that for the moment and created a task in our product backlog for minifying the size of those pages.
After using Expo to develop some features for the client’s app, we hit a dead-end. Expo did not support some of the features we needed, like background audio playback or Firebase Cloud Messaging to notify users about new podcasts in our app, even when they have the app closed. It seems that not all native APIs are supported in Expo. For example, at the time this article was written, some features were still missing, like Bluetooth support, WebRTC support, and more.
Unfortunately, on the Getting Started page for React Native, there was a barely-visible link to the Limitations of Expo, which listed the reasons why Expo wasn’t the right choice for our MVP. What a bummer! We had all this code intensely coupled to a software development kit that couldn’t deliver what we needed.
We had to find another way, so we first tried to decouple from Expo using the expo eject command. It promised to transform the project into what we wanted: only React Native modules, without Expo. Unfortunately, it did not work well, so we ended up bootstrapping again: this time a clean React Native app, without using Expo. We replaced all the Expo modules with React Native modules, and, while doing that, the software development workflow seemed familiar again: we built the app using commands, Gradle, Xcode, and other familiar tools. We were done being “wizards” who scan QR codes. 🙂
To make things better, the build size was considerably smaller (5 MB vs. 20 MB with Expo), we had better app startup times and improved performance. It seemed too good to be true.
And it was… too good to be true. To finish the app, we had to explore GitHub for libraries that offer basic features, which are omnipresent in other platforms: background audio playback, push notifications, store purchases, subscriptions, etc. We became frustrated, arriving at one bitter conclusion: except for those backed by Facebook, React Native has few quality libraries developed by third parties. Most of them are incomplete, buggy, filled with lots of hacky, immature code, abandoned, or undocumented.
To make things worse, React Native version upgrades broke up dependencies like no other platform we worked with. A small upgrade, like going from version 0.58 to 0.59, made our app builds fail. We always had to improvise new fixes to have a successful build, with no clear understanding of why things break so often with React Native.
After this adventure, we recommend that other software development teams cautiously adopt Expo and React Native, depending on their needs. First of all, you should educate yourself about the limitations of both. When you develop apps using React Native, it is a good idea to stick to the core components and APIs that are developed by Facebook, and not those created by third parties. Going this route may be a great idea when developing mobile apps that do not require many native integrations, for the following reasons:
However, if many native integrations are required, and they are part of the app’s core functionality, native apps may be the better approach, as they help you plan, estimate, and deliver more reliably. And we all know how precious reliability and predictability are for our customers.
This was our experience with Expo and React Native. If you found this story useful and feel that it is worth sharing with other software developers and tech companies, do not hesitate to tweet it, post it on LinkedIn, or Facebook.