I frequently get asked by prospects and clients if they should use React Native for their next big project. React Native, originally started by Facebook, is a cross platform framework similar to the React javascript framework that promises to allow devs to write code once, in Javascript, that will work on both iOS and Android. The answer to that question, in pure consultant speak, is “it depends”. You can do lots with React Native. It’s easy to pick up and roll an app, and you can achieve pretty much anything that you could in a native app.
But if you are betting your company or your product on the foundation of React Native, I’d think again, especially if you’re looking for deeper hardware integration. This five-part series of posts by the engineering team at Airbnb brilliantly describes the reason they decided to chuck React Native after 2+ years of investment. The answer, quite simply, is that it added too much complexity and didn’t allow Airbnb to achieve their goals. Let’s see why.
The promise of React Native for most people is cost and time savings. Having a single code base for both iOS and Android in theory lets you write once for both platforms, which (again in theory) means fewer resources (one developer can cover both platforms) and faster time to market (getting two platforms out with the effort of one developer). The reality, however, is much different.
It’s useful to review Airbnb’s original motivations and goals in moving from native to React Native. They were already using the React framework for their web products and hoped to leverage that familiar framework onto their mobile products, which were exploding in popularity and required a rapidly increasing number of engineering resources. So their goals were the following:
- Do more with less and move faster
- Keep quality high
- Write code once for multiple platforms
- Keep developers happy!
So did they hit their goals? Let’s start with what worked well, which were a lot of things.
The good: speed & uniform code
Ultimately 95-100% of their code using React Native supported both iOS and Android, with only a small percentage being platform-specific. They also note that engineers came up to speed quickly using this framework, and that the build cycle was much faster — you can do a React Native build in 15 seconds as opposed to 15 minutes for native builds (especially on XCode) — which is a big advantage over time. Additionally, React Native forced Airbnb to adopt a design language for their products that would be consistent between platforms. That discipline helped their developers. Also, because React Native is rooted in Javascript, that meant they could utilize the many open-source Javascript libraries available. The Airbnb team was generally pleased with their ability to build just about anything with React Native, at good levels of productivity, and with code that hit a very high percent of being shared across platforms. But the list of things that did not go so well is longer, and much more significant.
The bad: debugging & cross-platform compatibility
The first is that React Native, though it’s been out for 3 years, is still relatively new and moving fast as a platform. Just compare that to iOS or Android development, which have 10+ years of concentrated development. That it’s new isn’t necessarily terrible, but a fast-moving platform means that issues crop up in ways that are not predictable or easy to figure out. The Airbnb team spent a lot of time maintaining their own fork of React Native because of the need to fix issues. A fork is a complete copy of the master source code repository, which mitigates the reliance on the original source. But because they had their own fork, then the process of keeping React Native up-to-date became really hard, because Airbnb’s customizations had to be continually merged in. The next big problem results from the nature of React Native architecture (and all cross platform frameworks for that matter). React Native provides an execution environment for Javascript code, which bridges to native code. By its very nature, bridging adds a tremendous challenge to debugging. Where did the bug occur? In the native code or in the React Native code? Stack traces do not pass across the bridge, so if there’s an issue in native code it’s very challenging to debug. This may not be a problem in the future as the framework evolves, but developers face it today constantly; and in fact, the challenge of debugging was called out fairly frequently by the Airbnb team. Again, the complexity of React Native running on top of native code led to issues. Subtle differences in the Android setup and configuration vs iOS setup and configuration continually made it challenging to debug platform-specific issues. This got further complicated for the Airbnb team by the challenge of debugging in developer environments — e.g., with a simulator — versus in a deployed environment. The results didn’t match. Furthermore, the Airbnb team used Bugsnag to capture issues, but Bugsnag didn’t always play well with React Native. This, again, added more challenges to their debugging. In summary, bridging between React Native and native code turned out to be pretty hard to debug, but in subtle ways that were hard to track down. Much of that challenge comes from the inconsistency of how data is passed back and forth through the bridge. Turns out, to debug effectively you have to be an expert not just in iOS and Android development, but also React Native. Hence, the promise of “write once deploy twice” is simply shattered. In fact, one could surmise from Airbnb’s experience that it’s actually more work to support React Native as a 3rd environment.
The ugly: the failed promise of Javascript & performance
The promise of React Native is frequently tied to the plethora of open source libraries: nice in theory, but the reality is that most of the libraries that Airbnb tried to use had issues on one mobile platform or another. Libraries are typically written with native bridging, and the bridging is only as good as the developer who wrote it originally. This means that this developer has to be proficient, or an expert, on both iOS and Android. Of course, most developers only have expertise on one or the other so, yet again, a source of platform-specific issues come into play. Having to dive this deep to fix all these issues quickly erode the benefits of React Native altogether. Keep in mind, Javascript by its nature is not a typed language, so it’s easy for nasty little bugs to be introduced unwittingly. This fundamental issue with Javascript means that refactoring was at times incredibly daunting. It’s not easy to make big changes across a code base when conflicts in naming often easily lead so to confusion. (As a side note, Typescript works with React Native as well, and would probably scale better than raw Javascript.) And finally, we come to the elephant in the room: performance issues. Start up time for React Native is heavy and slow. The entire runtime environment for React Native needs to be initialized before things can start to happen. That’s why the Airbnb team had to utilize native code for launch screens, in order to make their app as responsive as can be during the crucial moments when users could easily be turned off by delays. It’s safe to say that the performance of native code is always going to be better than that of a framework that rides on top. It’s always been that way. That’s not React Native’s fault, but it’s the reality of the situation. Rounding out the list, here are the other big technical problems that Airbnb pointed out:
- There’s no support for 64-bit apps on Android with React Native, so you can’t take advantage of the performance capabilities of the latest hardware.
- They were not able to fully utilize gestures because of significant differences in gesture handling architectures on iOS vs Android.
- There are significant holes in React Native’s Accessibility support.
- There were major problems upgrading versions of React Native as it evolved.
Don’t forget the talent
And then there’s the issue of talent. As noted by Airbnb, to support React Native thoroughly, you really need expertise in iOS, Android, and React Native. It’s not easy to find engineering talent that knows two of those three skill sets, let alone all three. Of course, this problem surfaced again and again in debugging issues. And here’s where I’ll add from my own experience recruiting talent — the talent pool for people who know native Android or iOS development is just much bigger than for those who know React Native. This is not an insignificant detail for managers to keep in mind when deciding to go with this framework or not. Need evidence? Swift and Kotlin are highly ranked on GitHub’s list of active programming languages, and both Java and Swift are into the top 10 of Tiobe index of popularity. And of course, Swift is a very popularand loved language.
Summary
I’ll come back to what I said earlier: React Native may be appropriate in lots of cases, and as a consultancy Rocket Farm will use it when it makes sense. In fact of all the cross platform solutions out there, React Native is our favorite. But if you are betting your product or even your company on an architecture, going native is the way to go. Reach Native is more complex, harder to test and debug, and has real trade-offs in terms of performance. Complex organizations, as Airbnb learned, will find it harder to staff and maintain over time on such a framework. Every year like a drumbeat, Apple and Google improve and expand what their core platforms can do. Every year, frameworks like React Native must scramble to catch up. I’d rather stay close to the dominant players in the ecosystem and keep things simple. We had clients get absolutely torched by Facebook’s decision to abandon another popular framework called Parse 2 years ago. I never want to put a client in that position again. Note: special thanks to Matt Graziano for his thoughtful review and comments on this post. Matt is a strong proponent of React Native and we don’t always agree. Matt is the founder of Ambrao, a technology consultancy that specializes in web and cross-platform mobile app development for early stage companies looking to get their products to market.