Skip to main content

React Native at Airbnb

Free2019-08-31#Tool#React Native企业应用#React Native案例#Why not React Native#RN is died#RN and Flutter

The ups and downs of React Native at Airbnb

Preface

Airbnb boarded the React Native ship as early as 2016, being a very representative pioneer evangelist:

In 2016, we took a big bet on React Native. Two years later, we're ready to share our experience with the world and show what's next.

But announced Sunsetting React Native in early 2018:

Due to a variety of technical and organizational issues, we will be sunsetting React Native and putting all of our efforts into making native amazing.

What happened during the period from fully embracing React Native to returning to Native?

Betting on React Native

Manpower was tight, had to seek another path:

Back then, we recognized how important mobile was becoming to our business but simply didn't have enough mobile engineers to reach our goals.

And the new choice was React Native:

We saw React Native as an opportunity to open up mobile development to more engineers as well as ship code more quickly by leveraging its cross-platform nature.

Like Facebook's original intention for creating React Native, Airbnb also hoped to leverage React Native technology to move faster, without having to develop two sets of mobile code on separate platforms for one product feature. But as a bottom line, hoped this newly introduced technology could also meet Native's established quality standards

In fact, React Native did meet Airbnb's initial expectations:

Many of these features were built at a time where we simply did not have enough native engineers to achieve our goals.

But not without harm, discovered two difficulties in deep application:

  • Integration with Native complex features: such as shared element transition animations, parallax effects, geofencing, etc.

  • Cooperation with Native existing infrastructure: such as networking, experimentation testing, internationalization, etc.

Happy and Painful

However, its benefits didn't come without significant pain points.

From Airbnb's practical experience, React Native's advantages are:

  • Cross-platform: thereby achieving unification of three-end design language, and high code reuse between Web and Native

  • Fits JS ecosystem: seamlessly access Redux, ESLint, Prettier, reselect, jest and other JS ecosystem

  • Development efficiency: no need to wait for compilation, Flexbox layout is also easier to master

  • Native extension: any Native capability can be bridged into React Native, meanwhile, Native's existing infrastructure can also be integrated

  • Acceptable performance: animations are as smooth as Native, experience can satisfy most scenarios, rarely need to pay attention to performance

Code reuse and possibility of three-end unification brought by cross-platform features are irreplaceable advantages, and supporting JavaScript runtime enables it to enter JS ecosystem, thereby obtaining Hot Reloading and other compilation-free experiences, achieving development efficiency improvement

Actually, for the widely concerned performance issue, it's not as slow as imagined:

We frequently saw mobile engineers look at JS and think "slower than Java". However, moving business logic and layout off of the main thread actually improves render performance in many cases.

In some scenarios touching capability boundaries, can break through limitations via Native Bridge:

Because everything in React Native can be bridged by native code, we were ultimately able to build many things we weren't sure were possible at the beginning such as Shared element transitions, Lottie, Native networking stack, i18n, experimentation, etc.

Looks very perfect. But in some other aspects, React Native did indeed bring quite a bit of pain, such as:

  • Insufficient maturity: not as mature as Android, iOS, exists uncertain capability boundary risks

  • JS language deficiencies: weak typing makes refactoring very difficult and error-prone (early stage hadn't provided TypeScript support yet)

  • High threshold for library construction: writing React Native libraries requires familiarity with 3 platforms, otherwise platform-specific problems easily occur, very high requirements for developers

  • Poor support for some features: such as cumbersome Native Bridge API, early provided accessibility API was incomplete, long List support not as mature and flexible as Native solutions, gesture support, JS runtime environment exists platform differences... even long-term didn't support Android 64-bit (until version 0.59 in March 2019 supported Android 64-bit)

  • First screen performance fatal flaw: second-level runtime initialization overhead, and hundreds of milliseconds of前置 first screen rendering time, completely unable to meet performance requirements of splash screen and other scenarios

  • Extra burden: introducing React Native means package size increases by 8~12MB, meanwhile, since its ecosystem is not yet mature, development usually faces infrastructure and feature iteration in parallel

Technology's own maturity is insufficient, plus (high threshold for library construction leading to) slow open source ecosystem development, causing in actual use to cope with scenarios needing quick patches, usually need to maintain own fork of React Native, and this maintenance cost cannot be underestimated:

We had to maintain our own fork of React Native where we could merge fixes. For these case, a one-line fix on Android or iOS wound up taking days of figuring out how to add it to React Native, cherry picking it, then filing an issue on React Native core and following up on it over the coming weeks.

On the other hand, Native's years of accumulated infrastructure (crash monitoring, etc.) all need to be rebuilt under React Native (either rewrite or bridge), otherwise development experience and efficiency can't keep up:

Because React Native is relatively new and rare in the industry, we had to build a significant amount of infrastructure.

First screen performance main difficulties are:

  • Initialization time: initialization overhead of React Native runtime is unavoidable, large applications even on (2018) high-end devices need several seconds

  • Pre-time before starting rendering: must first go through JS thread, yoga layout thread, get enough information before can start rendering on main thread, during this period exists 280~440ms white screen time

P.S. Thread model limitations also brought some other problems, such as:

Many of the limitations are difficult to overcome because of the threading. Adapter data can't be accessed synchronously so it is possible to see views flash in as they get asynchronously rendered while scrolling quickly. Text also can't be measured synchronously so iOS can't make certain optimizations with pre-computed cell heights.

How Does Team Organization Cross-Platform?

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.

Technology also caused impact on organizational structure, these challenges may be harder to solve than technical problems

Requirements for Engineers

  • Balance three-end experience: React Native essence is still Native, therefore Native infrastructure is indispensable, and platform differences still exist, this makes balancing three-end experience quite difficult

  • Cross-team problem localization: React Native itself is still in rapid development and change, infrastructure and feature iteration in parallel, plus everyone doesn't have too much experience, makes problem localization exceptionally difficult, even can't figure out which team problem should belong to, or from upstream React Native

  • Cope with cross-platform complexity: engineers mostly familiar with one or two platforms, but building or debugging may involve other platforms. Worse, facing this cross-platform complexity, engineers may completely not know where to start investigating problems

  • Prepare three sets of development environments: React Native engineers need to have 3 sets of latest development environments, and each set of environment is not so easy to build, learn and keep updated, every few weeks need to spend several hours updating these environments

React Native cannot completely shield platform differences, then requires engineers to understand these differences, and carefully balance three-end experience. And complexity brought by cross-platform directly reflects in problem investigation chain, engineers may need to cross-team, cross-technology-stack locate problems

Challenges Faced by Team Organization

Teams may face some problems in members' perception, such as:

  • Polarized attitudes: practical experience shows, engineers' acceptance of this technology exists polarization, some view it as three-end unification silver bullet and fully support, some completely refuse and not willing to use at all

  • Perceived iteration speed slows down: from engineer's perspective, if compared with Native, using React Native to develop a feature needs 1.5x time, he will still think spent more time, although in fact (multi-platform) total time spent decreased

Under mixed technology stack, teams also need to consider some new problems:

  • How to divide teams, how to collaborate?

  • How to efficiently debug across technology stacks?

  • How to test across platforms, ensure code works normally on multiple platforms?

  • How to decide what technology to use for implementing new features?

  • How to recruit and allocate team resources?

In fact, this mixed technology stack did indeed cause a series of impacts on personnel recruitment, team division, technical implementation, training teaching, etc.:

  • Personnel recruitment: industry labeled enterprises with React Native tag, many engineers hesitate whether to join for this, affects personnel recruitment

  • Team division: mixed teams frequently face technical and communication problems, because code is split into two copies, engineers no longer familiar with entire logic flow, sharing business logic, models, states becomes very difficult. Although these problems can be solved through sharing resources and code, most teams haven't formed such good atmosphere yet

  • Balance multiple technology stacks: which code should be implemented by Native, which should be placed in React Native, needs weighing. And engineers usually don't consider these, tend to choose technology stack they're familiar with, causing some code not so ideal

  • Training teaching: compared to Native's 10+ years of resource accumulation, React Native related learning resources and documentation are still too few, means also need to invest some resources in technology and internal infrastructure teaching training

Abandon React Native, Return to Native

Although many teams relied on React Native and had planned on using it for the foreseeable future, we were ultimately unable to meet our original goals.

After 2 years of practical verification, confirmed React Native cannot completely meet initial expectations:

  • Move Faster: when smooth, development speed is indeed unparalleled, but various technical and organizational problems greatly slowed down this speed

  • Meet Native's established quality standards: React Native's continuous maturity and experience accumulated in practice brought some performance improvements, but some technical problems (such as initialization and first screen asynchronous rendering) still full of challenges, internal and external resource scarcity exacerbated this difficulty

  • No need to develop two sets of mobile code on separate platforms for one product feature: React Native code can almost all be cross-platform reused, but in Airbnb App this part of code proportion is very small, and needs to bridge large amount of infrastructure, so actual result is to develop on Android, iOS, React Native three platforms, not just Native dual platforms

  • Improve development experience: development experience is hard to describe, performs well on compilation time, but debugging experience is very bad

Due to all the above, after careful consideration, Airbnb finally decided to completely abandon React Native:

When we balanced the positives against the pain points plus the current needs and resources of our Engineering organization, we decided that it wasn't right for us anymore.

Specifically, since June 2018, all feature iterations no longer consider React Native technology, related open source projects no longer maintained, and plan to migrate high traffic business to Native implementation by end of 2018, gradually remove performance burden brought by React Native (such as initialization time at startup)

Native Development Inspired by React Native

Although gave up continuing to use React Native, but during these 2 years, Airbnb also received some very valuable inspirations for Native:

Today, we have a number of exciting projects in production or in the pipeline. Some of these projects were inspired by the best parts and learnings from our experience with React Native.

For example:

  • Server-Driven Rendering: dynamic updates

  • Epoxy Components: declarative component definition, lazy loading, update mechanism based on virtual DOM

  • MvRx: thread model

  • Compilation speed improvement: modular compilation

Server-Driven Rendering

Server-Driven Native Rendering (Server-Driven Rendering):

With these frameworks, the server sends data to the device describing the components to render, the screen configuration, and the actions that can occur. Each mobile platform then interprets this data and renders native screens or even entire flows using DLS components.

Used for dynamic updates and other scenarios:

Server-driven rendering frameworks have already provided huge value by allowing us to experiment with and update functionality instantly over-the-air.

Epoxy Component

Epoxy is a declarative Native component solution, supports Android and iOS:

Epoxy is a framework that enables easy heterogeneous RecyclerViews, UICollectionViews, and UITableViews.

Among them, borrowed React's component update idea based on virtual DOM:

The key to React's performance is that those components are just a data model representation of the actual views/HTML you want to render. The component tree is then diffed and only the changes are dispatched. We built a similar concept for Epoxy.

MvRx

Android development framework formed by merging common development patterns and some React ideas, MvRx:

MvRx is an opinionated yet flexible framework that was developed by taking common development patterns that we observed as well as the best parts of React.

Compilation Speed

Reduce compilation time by splitting modules:

We built infrastructure on Android and iOS to enable you to compile only part of the app that includes a launcher and can depend on specific feature modules.

Why So Difficult?

At this point, React Native's story at Airbnb ended

From betting on React Native, to encountering technical, team organization difficulties, to deciding to abandon after weighing pros and cons, finally转而 fully invest in Native system, and apply some of React Native's ideas into it... why so difficult? Even large enterprises cannot master this new technology?

Objectively speaking, many difficulties Airbnb encountered all originated from Native and React Native hybrid application (integrating React Native into existing Native App):

We integrated React Native into large existing apps that continued to move at a very fast pace. Many of the difficulties we encountered were due to the hybrid model approach we took.

Facebook until June 2018 only planned to solve various problems existing in hybrid applications through large-scale refactoring:

We're working on a large-scale rearchitecture of React Native to make the framework more flexible and integrate better with native infrastructure in hybrid JavaScript/native apps.

And many difficulties in these problems are what Airbnb experienced, and struggled with relentlessly. Compared with some small-scale enterprises, Airbnb has ability to go deeper and farther, so also encountered more and bigger difficult problems:

However, our scale allowed us to take on and solve some difficult problems that smaller companies may not have had time to solve.

Although early believer Airbnb chose to give up, but React Native still continues to develop at high speed, and becoming mature:

Facebook and the broader React Native community are dedicated to making React Native work for hybrid apps at scale. React Native is progressing faster than ever.

Therefore, for many other enterprises (Pinterest, Instagram etc.), React Native is still a good or even best choice

Reference Materials

Comments

No comments yet. Be the first to share your thoughts.

Leave a comment