blog content
The following article is part of The Ultimate Guide to React Native Optimization and describes how to automate the dependency management with <rte-code>autolinking<rte-code>.
Since the first release of our performance optimization guide, this article has undergone a significant update, and now, you’re reading its older version. To access the freshly updated content, download our performance optimization guide and check out the Avoid unused native dependencies chapter.
Why is it important?
Sometimes adding new packages to your React Native apps may cause issues with the native code. Moreover, this process may occur more time-consuming than you previously estimated. That's why you might want to learn how to automate your dependency management with <rte-code>autolinking<rte-code>, making this process faster, more efficient, and harmless to the native code of your app.
In other blog posts based on The Ultimate Guide to React Native Optimization, we touch on the following performance-related topics:
- Optimizing your Android application’s size with Gradle Settings
- Optimizing your Android app startup time with Hermes
- Debugging faster and better with Flipper
- Why is it essential to always run the latest version of React Native?
- Experimenting with the New Architecture of React Native
Be sure to check them out. Now let's jump into the main topic.
Automate your dependency management with autolinking
Issue: You’re adding libraries manually or using the deprecated react-native link
Unlike most of the packages available on <rte-code>npm<rte-code>, React Native libraries usually consist of more than just a JavaScript code. Depending on the type of functionality they provide, they may contain additional native code for Android and iOS platforms.
For example, a react-native-fbads is a React Native module used to interact with underlying Facebook SDK and, as the name suggests, to display ads within the application. To do so, the module ships with JavaScript code that allows you to call the SDK from the React Native realm. On top of that, it provides Objective-C (for iOS) and Java (for Android) native modules that proxy the JavaScript calls to the proper Facebook SDK parts. It also requires Facebook SDK to be present in your app. In other words, it leaves the installation of it up to you.
Historically, React Native didn’t provide an out-of-the-box solution for cases like that. Developers were encouraged to follow the best practices for a given platform.
On Android, the recommendation was to use Gradle, which was already a platform of choice within the Android community. React Native used Gradle for building its source code and pulling its own dependencies, which naturally enforced all community packages to follow the same strategy.
On iOS, on the other hand, the situation was a bit more complex. By default, React Native projects didn’t use any sophisticated tooling for managing dependencies - pulling them down was on you. Some community modules have started using CocoaPods, which was similar to Gradle, because of the way it structured the project and provided proper dependency management. Unfortunately, CocoaPods wasn’t compatible with how all React Native projects used to manage the dependencies by default.
React Native tried to partially solve this problem by introducing <rte-code>react-native link<rte-code> - a CLI command that once run, tries to perform all the necessary steps for you. It performed a naive find & replace within your configuration files and tried to add the required packages.
Unfortunately, there has always been a risk of hitting a dependency that is not compatible with the way you manage your dependencies. In that case, the only solution was to migrate to a system that works. That task alone wasn’t easy - it required a lot of native-related knowledge and an understanding of build systems. If you have ever upgraded to a React Native version that introduced certain native changes, you will perfectly know what we are talking about.
Over time, CocoaPods have started to become more and more popular within the community. Eventually, React Native decided to switch to CocoaPods and make it a default way of managing the external dependencies on iOS.
As a result, both iOS and Android now have a fully-featured solution for dependency management. Thanks to that, developers can use a npm-like tool to pull down the dependencies, instead of downloading the files manually and putting them somewhere on the disk.
While this has helped with the confusion around adding external native dependencies, the situation still called for additional steps to run after simple <rte-code>yarn add<rte-code>.
Thanks to the fact that both Gradle and CocoaPods have a public API that can be used to manipulate the project, React Native team quickly shipped a feature called autolinking. It automates all the mentioned steps and removes the differences between a React Native and JavaScript package.
<p-bg-col>$ yarn add react-native-fbads<p-bg-col>
Installing React Native package should be no different from a regular JavaScript library
Long story short, if you’re performing additional steps after installing React Native modules, you should keep on reading!
The codebase is harder to upgrade and maintain and you spend more time on adding additional packages
If you are still managing your dependencies “the legacy way” as described above, you’re missing out on the build improvements and automation. As a result, experimenting with new dependencies becomes more challenging and it takes longer to set them up. Some libraries may even cease to work as developers migrate them to the new build system.
Also, you need to spend more time on upgrading to newer React Native versions as there are a bunch of native dependencies and native code that has to be revised and upgraded.
The new system is based on dedicated native build tools, such as CocoaPods and Gradle. Because of that, it is able to handle a lot of those meticulous steps for you.
Solution: Switch to autolinking (CocoaPods/Gradle based)
Autolinking is a new way of managing your native dependencies that, by design, is fully transparent and does not require any additional effort on your side. It is very easy to integrate and it hooks in places that you had to handle yourself.
It works the same for both iOS and Android. For the purpose of this section, let’s focus on Android.
app/settings.gradle
Before
After
app/build.gradle
Before
After
MainApplication.java
Before
After
Rather than letting Gradle know the details of every package you’re using, you replace the list of packages with a single line that calls into the React Native CLI. This little helper checks your <rte-code>package.json<rte-code> for the possible React Native packages and automatically performs the necessary actions.
Here is an example: In build.gradle, the call into the React Native CLI results in an array of packages that are then registered in the pipeline. It is worth noting that paths are calculated dynamically, based on the location of your source files. Consequently, all different non-standard architectures, including popular <rte-code>monorepo<rte-code>s, are now supported by default.
Another great trait of autolinking is that it generates the list of packages for you on Android. Thanks to that, all the packages defined by your external dependencies are automatically registered, without the need to open Android Studio and learn how to import packages in Java.
The principle here is simple - you don’t have to be aware of what the library you are downloading consists of. The possibility of exploring those details should be left as an option to the most curious developers.
Benefit: You can quickly add new packages and don’t worry about native code
To sum up, automating your dependency management the way we described here has a huge positive impact on the mobile app development process. Thanks to autolinking, you can forget about all the differences between regular JavaScript and React Native packages and focus on building your application.
You no longer have to worry about external dependencies or additional build steps, including pulling SDK or linking assets.
In the long run, you will appreciate this approach for its ease of maintenance and the speed of upgrading. The CocoaPods, Gradle and React Native CLI helpers ensure that the knowledge needed to both set up autolinking and use it within the application is as basic as possible and that it is easy to grasp for JavaScript developers.
Summary
To sum up, automating your dependency management the way we described here has a huge positive impact on the mobile app development process. Besides coding, it also makes the maintenance easier and increases the speed of upgrading. What's more, this solution can make developers' work more time-efficient because the only thing they will focus on will be the process of building the app.
In the next part of our guide, we will tell you how to optimize your Android app startup time with Hermes.
Need help with performance? Give us a shout!
If you’re struggling with improving your app performance, get in touch with us.
We’re the official Meta and Vercel partners and active contributors to the community. We’ve delivered high-quality solutions for dozens of international clients, from startups to enterprises. If you have any React Native development needs, we’ve got you covered.