Mobile apps today aren’t just about retrieving & sending data to and from services. They are results of a combination of sophisticated state management, aesthetically pleasing animations, complex navigation flows, processing of huge data sets, inference of ML models, and much more.
Additionally, multiple developers spread across different teams are needed to deliver and maintain these features. We have seen a higher adoption rate of React native amongst app developers recently. The great vision by the RN core team at Facebook makes it a top choice for mobile app developers.
Using React native architecture and writing scalable React Native apps requires a good understanding of practices that can keep up as the size of your application grows. In this article, we will discuss a few tips to architect highly-scalable React Native apps.
Enabling solid constraints
To ensure that apps remain performant and scalable as the scope grows, teams have to be very vigilant about the architectural decisions they make. When it comes to better architecture for react native apps, one thing that makes a huge difference is having a good answer to the question of: “What happens when a change is happening in one module?” To ensure that your app doesn’t turn into a big ball of mud, a set of practices and constraints must be established at the very beginning of development.
Dividing apps into smaller, independent modules that are testable in isolation can be super helpful in maintaining development pace & quality over time. It also allows teams to work independently, resulting in a well-aligned, fast development process with seamless deployment and incremental upgrades.
Key takeaways:
- Best practices for large-scale React apps
- Monorepos
- Micro frontends
React Native Architecture – State management
State management is one of the most debated topics in today’s JS world, and we are seeing a lot of state management solutions pop up. It is a crucial part of apps, especially for medium- to large-scale applications.
Deciding which is the best amongst all of these solutions largely depends upon the requirements and team’s expertise. Important factors in selection can be developer experience, an ecosystem built around a library, or community adoption and support.
Redux has been in state management for a long time now and gained a lot of attention. Recent developments in Redux ToolKit & RTK Query have boosted its power to great extent. React Query is another awesome solution when your app is more API-centric. MobX, Recoil, and a few others are also making waves and might suit your requirements better.
Tools/Libraries:
Code sharing
The best part about React is its ability to port concepts and ideas from one platform to another. The motto “learn once, write everywhere” is more practical than ever before. If the foundations of React Native apps are laid down properly, it can enable teams to share a huge code base across different platforms including Web & VR. Teams can also leverage git submodules to share components and logic across different repos.
Libraries like expo and react native web are paving the way to porting 100% of the code base across web and mobile platforms. For small- and medium-scale apps this can be an ideal way to save money.
Tools/Libraries:
Theming
It’s rightly said that great design can lead to the best front-end architectures. While applying sophisticated techniques like monorepos & micro-frontends, a design language can serve as a cornerstone for solid architecture.
A good design system sets the tone for your design and development teams. Consistency across components used in different parts of the app allows developers to create better APIs for each component. This makes components more usable and avoids incurring extra technical debt over time.
Wrapping dependencies
Large-scale React Native apps usually depend on a lot of third-party libraries that help them work faster. As time passes, however, a situation might arise where a third-party library doesn’t serve its purpose as well as it did when we started using it or a better alternative might emerge.
In such cases, switching from one library to another can prove to be a costly decision. As this change can hit our app quite hard if the library in question is used widely across different modules. It is always good to wrap your own API around any such libraries and use them via wrapper across your app. This can be super helpful in the event that you switch third-party libraries.
Moreover, be wary of the fact that too much abstraction can make your code uglier, so be very careful and wise when introducing any such abstractions. Additionally, platform portability can be ensured if platform-dependent libraries are wrapped with custom APIs.
Maintaining code & repo quality
As an application grows in size, the execution of tests becomes more costly. Thus, it is best to plan ahead to save time, and make sure there aren’t any fundamental issues (such as typos) in our code.
Static typing & linting can help us avoid basic issues that could eat up tons of our CI resources. Issues like spelling mistakes, linting, static type checking, and package audits can be performed on a developer’s machine as soon as they commit any code to the repository. Git hooks can also assist in maintaining code quality across a large codebase with several contributors.
You can also use git hooks to check commit messages, make commit history more readable, and for generating automated changelogs.
Key takeaways:
Tools/Libraries:
- Commitlint
- Lefthook
- CSpell
- Linting
Testing
“Move fast & break things” is no longer an acceptable mantra in today’s world. Benchmarks and expectations are getting higher with every passing day. For apps being developed at a high pace, automated testing is the most crucial step for continued success.
An industry expert, who has been working as a software developer for the past 30 years, recently mentioned that testing is still the most difficult part of software development.
Thankfully, we have tools that can make testing a joyful experience.
For developers looking to start with testing in React Native, we have put together an in-depth guide to implement unit, integration, and e2e tests for React Native apps.
Key takeaways
Tools/Libraries
- Jest – unit testing
- React Native Testing Library – integration testing
- Detox – e2e testing
CI/CD
Today, moving fast is not just an advantage, it’s crucial for the survival of businesses. CI/CD gives you the ability to ship your apps with confidence and peace of mind. If done right, CI/CD can significantly increase the pace of development & distribution .
As discussed earlier, a top demotivating factor for many developers is sitting idle and waiting for processes to complete. It’s in the best interest of developers and businesses to automate tedious tasks so that developers can do innovative and productive work. Besides allowing developers to deliver apps and updates faster, CI/CD takes away the cost of managing & maintaining different environments on development machines. As mentioned in the McKinsey survey:
“Organizations with strong tools for continuous integration and delivery—are 65 percent more innovative”
If you want to leverage CI/CD for React Native apps, we’ve put together amazing guides for you to fully implement best in class CI/CD for React Native apps.
Key takeaways:
Tools/Libraries:
Performance Tracking
Like we mentioned earlier, moving fast is a necessity these days. It’s not always easy, and faster iterations can result in problems even when a solid test suite and CI/CD are in place. For tracking issues and monitoring the performance of your app as it is being used, you can leverage Firebase SDK for its performance monitoring & crashlytics.
Key takeaways:
- Firebase performance monitoring/crashlytics
- LogRocket crash monitoring
OTA updates
One of the top challenges faced by app developers is getting users to upgrade to new versions of apps. Unlike web apps, businesses have less control over what version of their app users are using. Both Android & iOS now have libraries and methods available to notify users whenever a newer version of the app is available. React Native In-App Update is an open-source library that wraps in-app updates for both android & iOS.
This might be useful for many apps but still isn’t enough by itself. Because most of the business & UI logic resides within the JavaScript in React Native apps, it is possible to update apps over the air. Microsoft CodePush enables us to update the JS bundle of React Native apps without bothering our users.
Key takeaways:
Developer experience
Developers are the core of every business that relies on technology. Delivering the best user experience is only possible when the people developing it have the best experience themselves. Developers equipped with the right development tools and processes are more committed and productive.
Automating repetitive tasks such as writing skeletal code, utility libraries, unit test cases, and performing testing, frees up a considerable amount of productive time for developers. Taking assistance from AI can also bolster the development speed of teams.
Key takeaways:
Conclusion
“…with proper design, the features come cheaply. This approach is arduous, but continues to succeed.”
As we write more and more code, our ability to foresee the future increases. We learn from mistakes and find ways to deliver more scalable products at a faster pace. Laying down solid foundations at the very beginning of development can ensure the reliability and quality of your code base as it scales. Any mistake in this phase can result in huge technical debt in the future.
Keeping the development experience of apps pleasant will result in better productivity. Enabling solid constraints in apps will help developers make fewer mistakes, and automation can boost your team’s confidence to ship features fast without worrying about things breaking. All of this results in business growth and better experiences delivered to end users.