Building a Cross-Platform Mobile Team
Adapting mobile for a world with React Native
This is the third in a series of blog posts in which we outline our experience with React Native and what is next for mobile at Airbnb.
In addition to the countless technical pros and cons of React Native, we learned a ton about what React Native means for an engineering organization. Adopting it is much more complex than adding a new library or pattern to an existing platform. Doing so brought to light a number of organizational challenges. Unlike technical challenges which can often be solved or effectively worked around, organizational challenges can be harder to detect, correct for, and recover from. Thankfully, our mobile culture is healthy but there are a number of things to be aware of when considering React Native.
React Native is Polarizing
In our experience, engineers approached React Native with wildly different opinions varying from praising it as a silver bullet that united Android, iOS, and web to being wholly against any use of React Native on their team. The same situation occurred after using it as well. Some teams had an incredible experience while others regretted it and reverted back to native.
Root Cause Attribution
While working on React Native, there were inevitable bugs, polish, and performance issues. However, there were many moving pieces:
- React Native itself moves quickly.
- We were doing simultaneous infrastructure and feature development.
- Engineers were learning React Native together and it was relatively new for everybody.
- Our documentation and guidance for debugging in development and production was inconsistent at times and could be confusing.
As a result, it was often difficult to find the root cause of a problem. Sometimes, it wasn’t clear which team an issue should be attributed or whether the issue was inherent to React Native.
React Native is Still Native
A common misconception is that React Native allows you to move away from writing native code entirely. However, that is not the current state of the world. The native foundation of React Native still rears its head at times. For example, text is rendered slightly differently on each platform, keyboards are handled differently, and Activities are recreated on rotation by default on Android. A high-quality React Native experience requires a careful balance of both worlds. This, paired with the difficulty of having balanced expertise on all three platforms makes shipping a consistently high-quality experience difficult.
Debugging Across Platforms
Even though we were investing in React Native, our mobile ambitions and teams continued to accelerate in parallel. However, through word of mouth in the community, many people began to associate Airbnb with React Native and some even believed that our app was 100% React Native. Even though this was far from the truth, many Android and iOS engineers were hesitant to apply to Airbnb as a result. Just in case you are one of them, we are still hiring!
Hybrid Apps Are Hard
The path of a world that is 100% native or 100% React Native is relatively straightforward. However, once you have a mix within your codebase, many new issues arise. How do you split up your teams? How do teams collaborate? How do you share state across your app? How do you ensure that things get tested? How do engineers effectively debug across three platforms? How do you decide what platform to use for a new feature? How do you hire and allocate resources across your organization? These are all problems with non-trivial solutions that will inevitably arise if you go down this path.
Three Development Environments
In order to be an effective React Native engineer, it is important to have a stable and up-to-date React Native, Android, and iOS environment. For an organization as large as Airbnb, each platform requires a significant amount of time to set up, learn, and keep up to date. Returning after just a few weeks often meant spending several hours getting everything back up to date.
Balancing Native vs React Native
There are many situations in which the optimal solution for a problem spans native and React Native. For example, our navigation implementation makes heavy use of Activities and ViewControllers and most of its code is native to each platform. Often times, it is not clear whether code should be written in native or React Native. Naturally, an engineer will often choose the platform that they are more comfortable which can lead to unideal code.
We found that engineers would primarily develop on one platform over the other due to convenience or comfort. Often, they would assume that if it works on the platform they tested on, it would work perfectly on the other. Most of the time, this was true which is a testament to the power of React Native. However, it was untrue often enough that it ended up causing frequent issues late in QA cycles or in production.
Teams that worked in native as well as React Native often faced both technical and communication challenges. Once the codebase was split between native and React Native, the code became fragmented. Sharing business logic, models, state, etc. became more challenging and engineers no longer had the expertise to work across the entire flow. We knew that this would happen from the get-go but thought that this might be balanced by an increased collaboration with web. A few teams did start to share resources and code across web and mobile but most weren’t able to realize this potential benefit.
Perceived Iteration Speed
One of our qualitative goals with React Native was to increase development speed. Often, React Native features were written by a single engineer instead of one for each platform. From the perspective of a React Native engineer, if it takes them 50% longer to write their feature than it would on Android or iOS, it feels longer to them even if it takes fewer hours overall.
Public Resources and Documentation
Android and iOS have had ten years and millions of engineers contributing to learning resources, open source, and online help. We leverage many resources such as CodePath to help people learn Android and iOS. Even though React Native has one of the largest cross-platform communities and can leverage React resources, it is still much smaller than Android and iOS. That paired with the fact that we had to build most of our infrastructure in-house meant that our limited React Native resources were over-invested in education and training relative to native.