Udacity’s mobile team recently removed features from the App that were developed using React Native.

We get a lot of questions about our usage or React Native and why we stopped putting resources and effort into RN.

In this article, I hope to be able to answer most of the questions we receive and delve into:

  • What is the size and composition of our team?
  • Why did we prioritize trying React Native?
  • What’s the reason for giving up?
  • What works? What’s not?
  • . There are more [expressions]

I certainly wouldn’t claim to be an expert on React Native. Others on our team have more experience than I do, but I’m sure they don’t claim to be experts.

I will talk about what to do and not to do in our particular situation based on our own experience. Whether React Native is right for your team/project is up to you, but hopefully this article provides additional useful data points for you to consider.

“React Native is up to you if it’s right for your team/project”

Again, I want to point out that this experience and advice came from Udacity’s mobile engineering team, not anyone else. The ideas here do not reflect the opinions of any other team using or building React or React Native content.

team

The first thing to get straight. What does our team look like? Team size, experience, and organization have the ability to make a real impact on the feasibility of React Native.

Our mobile team is distributed across iOS and Android platforms.

Team size

React Native was first introduced:

  • 1 iOS developer
  • 2 Android developers
  • 1 product manager
  • 1 designer

Today:

  • 4 iOS developers
  • 3 Android developers
  • 1 product manager
  • 1 designer

In the 18 months we’ve been using React Native, both our iOS and Android teams have continued to grow.

The team is led by a new product manager.

We have transitioned through multiple designers and design paradigms.

Development background

How comfortable is every team using Javascript and the React paradigm when introducing React Native?

iOS

The only developer on the iOS team with extensive prior Javascript and Web development experience was happy to develop with React Native.

Today, at least three out of four iOS developers are used to and comfortable with Javascript and React Native technologies.

Android

When React Native was introduced, one of the two Android developers was happy with Javascript. The other (myself) has very little background in Javascript, React or Web development.

Other Android developers who joined the team later also had little Javascript or Web experience.

Our Apps

What does our product do?

Our mobile app is designed to bring the Udacity learning experience to your mobile device. They support authentication, content discovery, program registration (and in some cases payments), and finally the consumption of learning materials for a variety of programs and content types.

These applications are also the testing ground for new experimental features and programs designed to improve overall user learning.

Code base size

  • IOS: 97,400 lines (.swift,.h,.m format)
  • Android: 93,000 lines (XML, Java, Kotlin, Gradle)

The same

With React Native, the functionality of the application is also very close.

Over time, the core experience is roughly the same, but each team has more or less increased experience with the other platform.

In addition, due to the expansion of international demand, localization and smaller APK size are becoming more and more important issues for the Android team. The Android team also works closely with teams in other regions to target non-ios market-specific features.

Why and how do we adopt RN

Why did we introduce it?

We’re starting to roll out new mobile-specific features. We want to experiment and validate quickly on both platforms, so cross-platform development is very attractive.

Because it was a new and stand-alone feature, it was seen as an opportunity to experiment with cross-platform development.

React Native was chosen for several reasons:

  • Improved feasibility as a cross-platform solution
  • Most (two-thirds of developers) teams are comfortable with Javascript and Web development
  • Improved development speed
  • Successful experiences from other teams outside the company

How did we introduce it?

The original React Native feature was built in a separate GitHub repository and incorporated as a Git sub-branch into the iOS and Android repositories, respectively.

This allows for very fast prototyping and can be released as a standalone product if needed.

More of the experience was prototyping, and we eventually introduced a second, larger feature in the React Native code base.

A time line

  • August 2016: Create React Native RepO for feature 1
  • November 2016: Feature 1 is released for Android
  • November 2016: Development of Feature 2 begins
  • December 2016: Prototype for Feature 3 begins
  • January 2017: The development of Feature 1 was completed
  • February 2017: Feature 2 is released
  • March 2017: Feature 3 prototype finished
  • November 2017: Android Update feature 2
  • December 2017: Feature 4 prototype as standalone application. Native support was eventually withdrawn due to performance issues
  • February 2018: iOS Update feature 2
  • April 2018: Feature 1 removed from the Android platform
  • June 2018: Feature 2 was removed from two apps

Incentive to remove?

The answer is straightforward.

We removed the last React Native code from the application because the only remaining features developed by React Native were taken offline and we no longer needed support.

“Why did we stop investing in React Native?”

This is a more interesting question.

Consider the following reasons:

  • The number of features developed simultaneously on both platforms is reduced
  • Increased demand for Android specific products
  • Disappointed with long-term maintenance costs
  • The Android team is not inclined to continue using React Native

What do we replace it with?

The React Native features we’ve deployed and removed no longer need support, so there’s no need for a replacement.

The good side?

What’s going well with React Native?

  • Getting started with React Native is really easy to build and run on both platforms
  • Ability to extract from the larger React and Javascript ecosystems using many existing Librayies and tools
  • We were able to prototype Feature 1 on both platforms simultaneously
  • A single developer on a cross-platform team can build most of the functionality for both platforms 2
  • The team’s common understanding of React Native has improved

What problems do we have?

During our use of React Native, we encountered a number of problems. Some of this is due to our workflow, some to our use cases, and some to React Native itself.

Design and experience challenges

Platform consistent UI/UX

Because we’re integrating some new screens into the existing larger user experience, we wanted the new React Native code to follow both the Native platform model and the existing style. This means that we may not be able to use the same UI design for both platforms.

It’s not difficult to make sure each platform has its own style in React Native, but it does require an understanding of the design paradigms used in each code base. At its simplest, this requires platform checking and custom widgets for each system.

For us, this usually involves talking to the developers and designers on each platform to understand what is needed, or using a single style for both. This often leads to a very different experience on the Android side than on other apps.

More complex cases require additional development platform-specific code to customize the application experience.

One such example is ensuring that the back/forward button icon fits. Due to the need to integrate the new React Native functionality into existing apps, Android specific Native code needs to be modified for the React Native code base to ensure the correct behavior of the back/forward icon and back button press.

Changes to the Native design may require changes to the React Native code to handle integration points

On more than one occasion, the navigation structure of Android apps changed, which required us to update the React Native code.

Instead of being isolated into its own Activity, the React Native function must be moved into a fragment, placed on a screen with a BottomNavigationView, and then coordinated between itself and other Native fragments.

This type of platform change requires going back to a separate code base, making the changes, updating the integration, and ensuring that the new changes don’t negatively impact the iOS platform either.

Device specific problem

“Fragmented,” “diverse,” whatever you want to call it, it leaves us with the fact that there are many more unique Android device configurations that require special consideration.

We’ve found many times that the layout doesn’t work with Android phones of different sizes. We found that animations that run smoothly on the latest iPhone or Pixel devices don’t work well on lower-end devices in international markets where Android is widely used.

These are certainly not the only React Native problems; These are common development challenges on Android, but as platform-specific checks and considerations increase, we have to start thinking about how much time is actually saved by using React Native.

Global growth

Internationalization became a bigger challenge for the Android team as we worked with React Native. We have several international offices requesting localization and apK size reduction.

String localization in React Native can be done because it does require additional Settings. In our case, it requires changes to a separate repository. This adds complexity to localization tasks, which is not ideal when seeking localization help from other teams. This directly reduces the frequency of localization of React Native features.

We were able to reduce the size of our APK during this time, but the size of the code containing React Native was quite large and we were unable to address these issues. After deleting the last RN function, our APK was reduced by about 10M, including resource deletion and React Native itself.

Integration challenges

Integration with native components and navigation structures

In our experience, integrating React Native into existing applications can be quite simple if it’s a standalone feature, however there can be some challenges if you need to integrate tightly with and communicate with existing components.

We often find ourselves needing a lot of bridging code to communicate between the React Native and React Native components. When we need to change where the React Native component fits into our navigation hierarchy, the code needs to be updated at least once.

Tools/build issues

Incorporate the updates required by React Native into the build process for each application. We used CircleCI (Continuous Integration tool) to build the project we needed to reconfigure to support additional React Native build steps.

As mentioned earlier, with Android, it’s not as easy as we might think.

Once our build needed to be updated to include the React Native tasks required, CircleCI’s release compile time increased by approximately 20%.

After removing the final React Native feature from our codebase, we saw the following improvements:

  • CircleCI compilation time was reduced from 15 minutes to about 12 minutes
  • Published APK size reduced from 28.4MB to 18.1MB

Android teams have also encountered issues with Android/Gradle build tools that clash with React Native. Recently we have been working on Gradle 4.

IOS teams also face considerable challenges.

The configuration build was a pain because our React Native file structure wasn’t standard. Due to our separate project repository, we pull ReactNative code from srcroot/ReactNative, and many existing build tools use the default app structure, which is /ReactNative/ios/… The ios.

In addition, we used Cocoapods for dependency management, which was originally suggested as a way to integrate React Native, but has since been deprecated. Our non-standard file structure further aggravates this situation, forcing us to include some nasty hacking operations in our Podfiles in order to read from the correct location.

Since Cocoapods is no longer the standard way to include React Native, Podfile updates rely on the community to update, which is not always synchronous. In several versions the CSS /Yoga dependency has been updated, but the Podfile references an incorrect version… In the end, we used some dark technology to solve the problem.

Finally, CI (continuous integration) for iOS projects is also a pain point. We now have to add an NPM dependency layer and ensure that they are properly updated before continuing with the installation. This adds a lot of time to our build steps.

There was also a crash issue because one version of NPM contained the package.lock file and the other did not, causing us to install an incorrect dependency version during the React Native upgrade.

The React Native challenge

The document

React Native has been developing rapidly as an ecosystem, and we found that documents often failed to keep up. Especially when we first adopted it, we found that certain versions of documents/answers might not be relevant.

Documentation for integrating React Native into existing projects seemed minimal at the time. This is one of the challenges we face in updating our CI builds.

As React Native continues to evolve, the documentation and support community contributions have improved. If we start today, we might have an easier time finding answers to some of these questions.

navigation

We started with NavigationExperimental, which is not the easiest navigation library to use. When ReactNavigation appeared, it quickly became widely accepted in the community, and NavigationExperimental was abandoned before ReactNavigation was truly fully developed.

performance

As mentioned earlier, performance issues are sometimes noticed.

We were able to make some really nice animations that looked great on standard iOS and Android devices, but didn’t work well on the low-end Android devices that are common in the international market.

Getting into the React Native part of the app took longer to load than we wanted. It often doesn’t look like a seamless transition.

When prototyping standalone feature 4, rendering performance was such an issue that React Native was abandoned to support the Native experience.

Lagging behind native platforms

Because it’s not built with iOS or Android, React Native sometimes lags behind the Native platform. It often relies heavily on the community to support new native features.

One example is the urgent need to provide SafeArea support for iPhone X devices. We ultimately chose not to use SafeArea support for this feature for a short time. Using SafeAreaView is an example of the platform-specific capabilities that cross-platform developers need to understand to develop compatible applications.

At other times, React Native has lagged behind in adopting new platform requirements, such as requiring Android apps to be developed against API 26 by August 2018. There are several unsolved problems with this requirement.

Break the update

React Native’s non-backward compatible upgrades are frustrating. An example of this is when The PropType was deprecated when React Native updated its underlying React library.

Without maintaining our own custom branches, many third-party libraries would become unusable.

Maintain the challenge

Maintaining the React Native part of the code base can sometimes be a challenge. As mentioned earlier, Android often requires additional work, whether it’s integrating with existing code or fixing UI adaptation issues. This results in iOS and Android working on different branches of the React Native code base, so one platform doesn’t slow down the other.

As a result of this branching, the code diverges slowly and the effort required to make them parity increases. As a result, updates to one platform are not immediately added to the other.

React Native’s speed of change also poses challenges. Updating a dependency for new functionality or bug fixes is not always quick because changes can be broken.

Again, sometimes this leads to increased collisions, which can slow down code maintenance. Due to the small team size and limited energy, if it wasn’t easy/quick fixes in React Native code, it would be much less likely to handle due to the additional development work that might be required.

After adding React Native, it’s not always clear what level of error exists. Does it exist on both platforms? Or just on one platform? If only on one platform, is it in the React Native code or React Native code? The added complexity of these issues can sometimes slow down the quality assurance process.

When it comes to fixing issues in the React Native part of the code base, we now have to consider both iOS and Android, and may use three development stacks instead of one.

In addition, less than 100% of the team felt React Native was efficient, and the number of developers who could jump in and fix something quickly was reduced.

What can be done?

I’m sure some of the issues we encountered were specific to our use cases, but we could do something different to mitigate some of them.

Reduce differences

We could have done a better job of keeping each application in sync with the latest changes in the React Native Repo. I believe that keeping these updates in sync will help us develop stronger true cross-platform development for these features.

Testing on more devices, especially Android, caught more UI/performance issues early and allowed us to fix them before we went live. This also reduces the number of code disagreements by resolving problems before new requirements start working.

More consistent design

A more specific design from the start would have improved the functionality’s native look. One concrete example is using text/margin values that are consistent with other native applications, rather than selecting a new value in a new experience and using it on both platforms.

Better team understanding

Team members less familiar with React Native may have made more effort to accommodate additional development tasks. This increases the number of people who can solve code problems quickly.

Is there a use case that we think is more appropriate?

I don’t think anyone on our team thinks React Native doesn’t have its advantages. I certainly believe React Native is perfect for use cases.

Do you need to quickly build/build new applications from scratch on both platforms?

Are you building an application/feature that looks/behaves the same regardless of platform?

Do you have Javascript developers with alternate development cycles that you want to contribute to mobile devices?

If the answer is “yes” to any of these questions, React Native may be a viable option for you.

In particular, I think React Native is a very attractive option if you have a Javascript/React background and are looking to build an application that doesn’t require much Native code. It will enable you to start building on mobile devices without having to learn two different technology stacks.

React Native is also a good choice for fully cross-platform application development.

Will we use React Native again?

The iOS and Android teams disagree.

iOS

Possible. IOS teams are usually happy to work with React Native and consider using it to build new features. Also, on the product side, our product managers have more confidence in the React Native solution running on iOS than Android.

Android

Don’t. Ideally, the Android team won’t be working on React Native in the future. We found the React Native component to be a hassle and felt that the experience on all Android devices was not great.

In addition, there is a tendency to stick with a single development technology war, rather than adding new layers of abstraction and possible bugs on top of the Android framework.

Our feeling is that React Native runs new features faster on Android, but it takes longer to get from early stages to perfect releases to long-term maintenance.

Will we come up with another cross-platform solution?

As a team, we probably won’t commit to cross-platform development in the near future. IOS teams can build things with React Native and still be limited to iOS, as their teams generally prefer this experience.

Personally, team members will continue to focus on React Native and Flutter. As solutions like React Native and Lutter continue to evolve, we’ll continue to evaluate them for our teams.

That’s where we are today.

We have a better understanding of how React Native fits into our team and roadmap. We can use this information to make informed judgments about the right technology choices for our team.

“Can we say for sure if React Native is right for you? No.”

We saw the benefits and limitations of React Native. Can we say for sure if React Native is right for you?

No.

However, hopefully our experience will provide you with some additional reference points when evaluating whether React Native is appropriate for your project.

Why do you need to learn Kotlin besides Java? Airbnb is ditching React Native!

About me: Yifeng, blog address: Yifeng. Studio /, Sina Weibo: IT Yifeng

Scan the QR code on wechat, welcome to follow my personal public account: Android Notexia

Not only share my original technical articles, but also the programmer’s workplace reverie

Easter egg: public number reply keyword “interview information”, obtain BAT interview bull for you to prepare a full set of interview information!