One of the main tasks I fulfill as TechWyns CTO is assessing the technical and cultural fit of new employees. My involvement normally begins at the final stages of our hiring process, where I can do my part in making sure TechWyns always hires the best candidates. But, beyond that, I’ve also found these moments are a great opportunity to learn more about the insights and interests of many different developers.
For example, most of my recent conversations with top cross-platform mobile developers have had one thing in common: an increasing level of excitement for Flutter when compared to React Native. Since React Native is one of the main technologies we use here at FSL, I got curious and started doing some research on the “flutter vs react native” dilemma. Naturally, I had to write an article about it, so let’s start with some of the basic concepts.
What Is Flutter?
Flutter is an open-source mobile UI framework designed to help developers create native applications for mobile, web, and desktop using only one codebase. It was created and officially released by Google in 2018, and it’s arguably just starting to become a mature technology in the mobile development industry. From what I’ve seen, there are two things that make Flutter stand out to mobile developers:- The Flutter SDK: Flutter’s Software Development Kit goes beyond the standard collection of tools used to develop mobile apps and includes some incredible tools to compile code into native code for iOS and Android.
- The Widget Library: As a framework for mobile development, Flutter comes with an amazing UI library that’s based on reusable widgets. This way, developers can easily personalize UI elements (a.k.a., buttons, form fields, sliders, etc) according to their needs and the needs of the project.
- Plugin Ecosystem: Flutter ships with an amazing plugin ecosystem that opens up a lot of possibilities for developers. Thanks to this, integrating features GPS location, Animated UI Controls, and SQLite management is faster and easier.
What Is React Native?
React Native is a JavaScript framework that allows rapid development of native applications. Just like Flutter, React Native is open-source and created by a tech giant, Facebook. Since its release in 2015, React Native has been commonly used for building native applications in all kinds of platforms, including Android, Android TV, iOS, macOS, Windows, and Web. Here are a few reasons why React Native has been so successful in native development:- Platform Agnostic Components: React Native allows developers to create truly native apps by providing a series of platform-agnostic native components that map directly to the platform’s UI building blocks. In fact, this is one of the main reasons why Coinbase built its mobile app 100% with React Native.
- Declarative UI Paradigm: React Native components are designed to wrap existing native code and interact with native APIs following a declarative UI paradigm. Along with Fast Refresh (which is React Native’s implementation of “Save, See, Repeat” iterations), that makes collaboration between developers a whole lot easier and facilitates a seamless cross-platform development experience.
- Built On Top of React: As the name implies, React Native is built on top of React, the popular JavaScript library used by countless developers to create interactive web applications. The reliability, flexibility, and evident love from the community for this technology eased the transition towards React Native for a lot of developers.
The Popularity Matchup
To start anecdotally, nearly all of the developers I have talked to or heard discussing cross-platform mobile technologies have been more excited about Flutter than React Native over the last year. This correlates with the data in Stack Overflow Trends, which shows that Flutter overtook React Native sometime in 2019. Since then, React Native has leveled out and Flutter is holding an upward trajectory. But the correlation doesn’t stop there. Several other sites show that, when comparing the best cross-platform mobile app development technologies, Flutter is consistently trending up while React Native holds or slightly declines. For example:- A quick look at Google Trends shows that Flutter also surpassed React Native in early 2019, and currently React Native is on a slight decline after reaching peak interest a few months ago.
- In terms of GitHub contributions, the React Native vs Flutter dilemma is clear. Flutter has consistently maintained higher numbers and, at the moment, it appears to be trending up whereas the opposite is true for React Native.
- Finally, GitHub Pulse activity shows that Flutter has been far more active over the past month in every metric.
Comparing React Native and Flutter
Now that we know quite a bit about React Native and Flutter, we can start comparing them in more specific categories. For this, I thought it would be best to focus on a few major categories and select a relative winner for each. The Programming Language: Dart vs JavaScript Comparing Dart vs JavaScript is a massive topic that would probably take us a whole series of articles to tackle properly, especially because this isn’t an apples-to-apples comparison—Dart is designed to compile to JavaScript and native code. So take this quick comparison with a grain of salt.- Maturity: JS has been around for a lot longer, so it is clearly the more mature and stable language. Even though the Google devs have put a lot of work into making Dart easy to use, it is still relatively new to programmers and there’s not a lot of learning resources compared to JS. So point for JavaScript +1.
- Popularity: I spent a lot of time in this article arguing the growing popularity of Flutter and the stagnant growth curve of React Native. However, in terms of programming language popularity, JavaScript wins by a landslide. JavaScript is simply everywhere and it’s a must for virtually every single mobile development project out there. JavaScript +1.
- Productivity: This is a complex one. On one hand, JS has a lot more libraries and available resources thanks to its massive community and long-time market presence. On the other hand, Dart is a newer, more optimized, and purposefully designed language for cross-platform development. Since we’re mainly talking about mobile development productivity here, I’ve got to give this one to Dart +1.
- Speed: As an interpreted language, JavaScript is well-known for being lighter and faster for native development than compiled languages like Java. However, recent benchmarks put Dart ahead of JavaScript. This is attributed to the fact that Dart can be compiled both ahead of time and just in time, which are great speed boosts in Flutter development. While results may vary, the general consensus shows Dart has higher chances of being faster, so Dart +1.
- Flexibility: Both Dart and JavaScript can be used for web and mobile application development. However, Dart is rarely used for web development and JavaScript offers so many choices in this field that’s literally not fair to compare the two. In mobile development, Dart uses Flutter to focus on widget-based development, which is arguably a lot less flexible than what JS frameworks and libraries can bring to the table, so this one has got to go to JavaScript +1.
The Underlying Architecture
According to the official Flutter documentation, Flutter’s architecture is designed as a layered, extensible system. In other words, it exists as a series of independent libraries that always depend on their underlying layers. No layer has privileged access to the layer below it, and every part of the framework level is designed to be optional and replaceable. At the core of Flutter is the Flutter Engine, which is written in C++ and supports all the flutter primitives. Developers normally interact with Flutter through the Flutter Framework, which is the modern, reactive Dart framework we’re used to seeing. At this level, we can find the foundational classes, the rendering layer, the widgets layer, and the Material and Cupertino libraries. For further information, please refer to the documentation linked above. React Native’s architecture is Flux, the application architecture that Facebook uses for building client-side web applications. It is based on the concept of Unidirectional Data Flow, and made of four individual components:- Actions, which are helper methods that facilitate parsons data to the dispatcher.
- Dispatcher, which receives actions and broadcasts payloads to registered callbacks.
- Stores, which are containers for the application state and logic and which store all of the callbacks registered to the dispatcher.
- Controlled Views, which are React Components that grab the state from Stores and pass it down via props to child components.
The Performance Race
When it comes to performance, Flutter takes a very different approach than React Native or even native development. In essence, the fact that the Flutter framework is compiled using ARM C++ allows it to get as close to machine code as possible and, consequently, allows for better performance in most scenarios. React Native, in contrast, compiles its UI components into their native equivalents, runs JS on a separate thread, and communicates directly with native modules using bridges to ensure all needed actions are fulfilled. This means that Flutter’s widget-based system makes it a great option for performance-optimized applications that need to use as little CPU and memory as possible. React Native, on the other hand, often needs additional components to achieve UX targets, which naturally reduces performance just slightly enough to be considerable. All of this is illustrated with several examples on this benchmark. Additionally, the Google team just released Flutter 2, which now supports Progressive Web Application (PWA) development using the same code base as mobile projects. Flutter 2 also provides support for high-performance 2D and 3D APIs and hardware acceleration, and companies like iRobot and Rive have recently released performance-driven web and mobile applications that leverage these features. Based on this information, I believe that Flutter is better for performance-driven applications, so we’ve got to give it this round. However, there’s a lot that goes into measuring performance, so your mileage may vary.Testing with React Native and Flutter
When the time comes for testing, most React Native applications use Jest, a JavaScript test runner maintained by Facebook. Since version 0.38, a Jest setup is included by default when running react-native init and automatically adds the necessary configuration to the package.json file. This also creates a jest.preset node environment that mimics the environment of the React Native app, and avoids loading any DOM or browser APIs to improve startup time. Still, since many React Native and third-party components rely on native code to be rendered, Jest is forced to include a manual mocking system that can help to mock out the underlying implementation. Common third-party components like video can easily be mocked, often with just a few lines of code, but more complex manual mocks are required for forwarding prop types or static fields. For component and integration testing, React Native developers often use React’s Test Renderer and the React Native Testing Library. However, at this level the testing frameworks are only running JavaScript tests in a Node.js environment, so they do not take into account any iOS, Android, or other platform code which is backing the React Native components. In Flutter development, unit testing is fairly simple, as developers only need to test Dart classes using the dart package. Then comes widget testing, which is analogous to component testing. Testing a widget involves multiple classes and requires a test environment that provides the appropriate widget lifecycle context, but everything is included in the flutter_test package, which ships with the Flutter SDK. These are the tools included:- The WidgetTester allows building and interacting with widgets in a test environment.
- The testWidgets() function automatically creates a new WidgetTester for each test case, and is used in place of the normal test() function.
- The Finder classes allow searching for widgets in the test environment.
- Widget-specific Matcher constants help verify whether a Finder locates a widget or multiple widgets in the test environment.