How to Improve Your React Native App Performance

How to Improve Your React Native App Performance

React Native holds great promise for developers building cross-platform applications, and within a short span of time, it has passed the likes of Xamarin and Ionic.

React Native is a hybrid framework, which lets you build Android, and iOS application with easy code-sharing, and a faster shipping cycle.

However, often developers complain about performance issues in React Native, and it's the only bottleneck that's slowing down the adoption in startups.

React Native performance relies on the architecture, Native components, and libraries that you might be using in your application. 

The more tabs, navigations, controls, and animations your application has, the slower it responds to user interactions.

Whenever you update your application, those changes get implemented from one version to another.

And, that consumes resources and keeps slowing down your performance.

To understand the performance bottlenecks, you first must understand the underlying architecture.

React Native Architecture

Image title

React Native is based on JavaScript, in which the React Native part interacts with the Native thread through a bridge. So, the React Native Architecture has two main parts:

If you look at the React Native GitHub page, there are tons of issues being reported by developers. Some issues are inherent, and others are implementation errors which can be easily resolved.

I analyzed 23 applications built on React Native and picked over 35 performance issues to write about. Here, I'm only discussing the major issues, so if you want to read more, you can follow the original source.

Moreover, I have also given insights on how to understand the root cause and resolve it to improve your application performance.

Memory Leakage

Memory leaks are pretty common issues for Android applications with a lot of unnecessary processes running in the background.

Credit: Medium

To fix memory leaks in Android applications, you can use scrolling lists such as FlatList, SectionList, or VirtualList instead of Listview.

Scrolling list also helps in smoothing the infinite scroll pagination, so if you're building an application with a pull to refresh feature, and large data points, then you should consider using it.

Large Application Size

JavaScript applications rely heavily on Native components and third-party libraries. The more components you use, the larger the impact on the Application Size.

To reduce the size, you have to optimize the resources, use ProGaurd, create different app sizes for different device architectures, and make sure to compress the graphics elements, i.e. images.

Moving Components From the Native Realm to the React Native Realm

The components on the JavaScript side use a bridge to communicate with the Native side. For developers coming from a web background, it's a challenge to keep both threads in sync.

However, you can follow these practices to reduce the load on the bridge and improve your app's performance:

  • Check the stability of open source libraries before you use them. Boilerplate codes in libraries often slow down the rendering performance.

  • Some components make heavy use of message queues while communicating with the Native side, so you should not pass them on the main thread.

Navigation Components

Since the inception of React Native, the core development team has tried to improve the navigational performance between the JavaScript and Native elements. But, there are still issues associated with the navigation, which needs to be optimized.

In React Native, there are 4 navigation components that you can use in your application:

  • Navigator: Mainly used for prototyping and small applications, not good to deliver Native-like performance.

  • Navigator iOS: As the name suggests, it's only available for iOS.

  • Navigation Experiment: Was built to solve many pending GitHub issues, and still being used by many applications. However, Airbnb found it difficult to work with.

  • ReactNavigation: The performance is smooth and it is being used by 60% of the React Native applications.

If you ever wondered about the navigational difference between React Native and Native screens, here's a GIF that explains the difference visually:

image

App Launch time

Improving app launch time is an endless cycle of evaluating each and every component, looking for better performing libraries, reducing dependencies, etc. Often, an app's launch time is one of the biggest factor contributing to user churn.

To improve the launch time of a React Native application, you have to take care of the Object.Finalize element which often slows down the app performance for users.

Even minor use of finalizers can lead to out-of-memory errors in your app, even though there is significant memory available.

Finalizers run on a single thread. If there are 1000 finalizers waiting to be run, you can imagine the time it would take to execute them all. This creates huge dependencies on the application before the launch.

Device Orientation

Some React Native applications crash on changing the screen orientation from portrait to landscape. This might be a deal breaker for many users, especially in gaming or video applications.

Initially, developers were relying on react-native-orientation as one of the solutions to this challenge. But, we found out that react-native-navigation isn't able to determine the orientation lock on iOS devices.

More success with device orientation changes can be achieved by listening to the app's root view. 

Multithreading

Going back to JavaScript threads, React Native doesn't support multiple threading, so multiple services can't run at the same time.

When React Native is rendering one component, other components have to wait till the first one is rendered.

Twitch had to move away from React Native because they couldn't implement a live chat feature along with a live video feed.

Infinite Scrolling

As we wrote before, a big part of software engineering is optimizing for performance.

Infinite scrolling's default implementation in React Native is often the biggest performance bottleneck for newsfeed type applications, where they have to process large data sets.

There are two ways to which you can implement infinite scroll:

Image Caching in React Native

Image caching is important for loading images faster. As of now, React Native only provides image caching support on iOS.

For Android, there are a few npm libraries available, which does solve the image caching issue; yet even these don't offer the best performance.

A few challenges that we encountered are:

  • Cache miss: Whenever an app's page is refreshed, often these libraries fail to fetch the previously loaded images.
  • Performance lags when the caching logic is running on the JavaScript side of the application.

Image Optimization in React Native

When you play around in React Native, it is very important to use responsive images. Otherwise, you may find that your app delivers sub-par performance and multiple error messages.

To optimize images in your React Native application, follow these best practices: 

  • Use smaller sized images.

  • Use PNG as opposed to JPG.

  • Convert your images to WebP format.

WebP images can speed up your image loading time to 28%.

Maps in React Native

If you're working with a map feature, you will find that the dragging and navigation are pretty slow in React Native. 

While integrating the map library in your React Native application, make sure to remove the console.log, so it doesn't store any data in the Xcode, and disable the auto-update of regions.

The goal here is to reduce the load on the JS thread, which improves the interactions with the map. 

API JSON Data Optimization in React Native

Mobile applications always need to load resources from a remote URL or service, and, to perform such actions, developers make fetch requests to pull data from that server.

The fetched data from public and private APIs returns in a JSON form that has complex nested objects

Most of the developers store the same JSON data locally for offline access, and the performance suffers because JavaScript applications render JSON data slowly. So, it's recommended to convert raw JSON data in simpler objects before rendering.

Frozen UI in React Native

Frozen UI occurs when there is a long operation running on the main thread, and the main thread blocks the UI thread from rendering. This situation gets even worse while rendering custom animations, large files, raw JSON data, or lots of map data.

To avoid this issue, don't use Object Finalizers, and make sure to not run heavy objects on the main thread.

Conclusion

React Native is a complex platform in terms of its architecture and its different components, libraries, and Native modules.

But, ever since its inception, organizations like Facebook, Airbnb, Instagram, Skype, and Tesla have trusted React Native to build their applications, which are being used by millions.

That commitment shows that React Native does have the potential to be the preferred choice for building high performing applications.

We have put together all major performance issues, along with countermeasures to improve your app's performance. Feel free to share your thoughts!

Source : https://dzone.com/articles/react-native-app-performance-major-issues-and-insi

Related Posts