One of the main tasks I fulfill as FullStack Labs’ 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 FullStack Labs 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.
Another aspect that makes Flutter unique is the programming language behind it: Dart. Dart was announced by Google back in 2011 at a GOTO conference in Denmark, where it was presented as an object-oriented, class-based, garbage-collected programming language with C-style syntax that could compile to native code or JavaScript. However, the beta wasn’t released until two years later and it initially received a mixed reception by the mobile development community.
Since then, Dart has certainly improved a lot and the growing popularity of Flutter is proof of it. Today, Dart is seen as a very powerful programming language, and Flutter developers especially appreciate its support for inheritance, interfaces, and asynchronous programming. In fact, I believe most people would agree that the grand majority of mobile developers (and even React Native developers) are choosing to learn Dart because of Flutter. If you’re interested, here’s what a Hello World app looks like using Dart and Flutter:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
child: Text('Hello World'),
),
),
);
}
}
Finally, we can’t really talk about Flutter without talking about its widget-based system. The idea behind Flutter is to combine different widgets that provide developers with everything they would need to build an entire UI. As I briefly mentioned before, these widgets can be used to define almost any type of UI element, including structural (buttons, menus), stylistic (fonts, colors), layouts (padding, sizes), and many other types of elements.
Keep in mind that Flutter uses its own ready-made and native-looking widgets for this and it never uses OEM widgets, as some of the new people learning Flutter might think. Developers can also create their own custom widgets and use reactive-style views that compile Dart ahead of time into native code for multi-platform apps.
There’s a lot more to say about Flutter, but I feel this is enough to give you a rough idea of it. We can take a better look at it when we start comparing it to React Native, so let’s move on.
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.
In essence, the working principles of React Native are almost identical to the ones of React. However, note that React Native does not manipulate the virtual DOM, and instead runs background processes directly on the native platform. Also, React Native does not use HTML or CSS. As Mark Zuckerberg famously said in 2012, HTML was never the path towards true native experiences.
To solve the markup language problem, React Native uses a mixture of JavaScript, JSX, and a special markup code known as JXL, which is considerably resemblant to XML. This way, React Native gains the ability to communicate with both JavaScript-based threads and Native app threads. In the spirit of making a quick comparison with the Flutter syntax, here’s what a Hello World app looks like in React Native:
import React from 'react';
import { Text, View } from 'react-native';
const HelloWorldApp = () => {
return (
<View style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}}>
<Text>Hello, world!</Text>
</View>
);
}
export default HelloWorldApp;
In 2018, React Native had the 2nd highest number of contributors out of all repositories in GitHub and it remains one of the top ones to this day. Their community is as strong as it has ever been, and thousands of big-name companies have already rewritten their apps with React Native. Some of the most notable ones are Coinbase, Shopify, Uber, Erikson, Facebook, Instagram, Pinterest, Discord, SoundCloud, and Skype.
React Native has stood out as a unique cross-platform development solution because of its incredible code reusability, rapid cross-platform development, a large development community, and native-level performance. With all of that said, let’s move on to the actual comparison of Flutter vs React Native in 2021.
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.
I also posted some of my initial thoughts about Flutter vs React Native in this Twitter thread, starting with a quick survey that got the following results:
All of this data comes to show what you’ve probably realized already: Flutter is getting comfortably ahead of React Native. However, with only 13 thousand apps using Flutter at the moment (in comparison to React Native’s 31 thousand), React Native still has a significant dominance in mobile stores and we have yet to see how many more companies will ultimately choose Flutter for their upcoming projects.
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.
It seems like React Native takes this round. Let’s move on.
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 Dispatcher is perhaps the most important component of the bunch. It differs from generic pub-sub systems in two ways: first, callbacks are not subscribed to particular events and, second, every payload is dispatched to every registered callback. Along with Node.js’s EventEmitter, Flux will use the Dispatcher to set up an event system that makes it easier to manage the application state. Further information can be found in their GitHub documentation.
With all of that said, determining who wins this round is a bit pointless from a general perspective. Both React Native and Flutter have great underlying architectures—otherwise, they wouldn't be as popular as they are. Choosing one or the other based on their architecture is mostly dependent on the particular requirements of the application, so I’ll leave this score to you.
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.
Arguably, the widget testing tools provided by Flutter make testing an easier and faster job than testing in React Native. So we’ve got to give this one to Flutter.
Development Speed
Since they are designed for cross-platform development, both React Native and Flutter are great for development speed and can reduce traditional project delivery time by up to 50%. They also both have their own implementation of “Save, See, Repeat” iterations (Fast Refresh for React and Hot Reload for Flutter), and they both work extremely well. However, the final development time will always depend on two things: the knowledge of the development team in the technology and how many developers you can actually hire.
React Native has clearly been around longer, and the market dominance of React and JavaScript has motivated countless developers to learn and apply this library in their native development projects. After all, learning and implementing the native version of a library you already love is not a hard decision.
In contrast, Flutter hasn’t had as much time to attract as many mobile developers, even if it’s significantly trendier right now than React Native. This means that there aren’t as many developers with a lot of seniority in Flutter development, and it might be a bit harder to find the right people for the job.
Taking all of this into account, development speed is likely to be higher in React Native development projects. However, Flutter does provide many different IDE integrations that can really speed up development. Even on VIM, Flutter allows developers to use tools like IntelliSense, autocompletion, and validation. None of that is available on React Native unless you use TypeScript and the package supports types. So, in terms of potential, Flutter could be the faster development technology.
Community and Ecosystem
Popularity aside, both React Native and Flutter have amazing communities of developers behind them. And, contrary to what you may believe after reading the popularity section of this article, the numbers are fairly close. Here’s a quick glance at some relevant community stats for each technology:
As of the publication date of this article, the numbers in these tables show that the React Native and Flutter communities are very similar in size. However, Flutter has had three fewer years to build its community, so I find it quite amazing that it has managed to surpass React Native by significant margins in some of these metrics. With Flutter, it’s all been about its accelerated growth curve, as shown by this graph.
Beyond that, I think it is also valuable to take a look at some of the major apps using these technologies. On one side, some popular React Native apps are Facebook, Tesla, Bloomberg, Instagram, Coinbase, and Uber (we actually know a little bit about this last one, since FullStack Labs worked on a React Native project with Uber). On the other side, some popular Flutter projects are Google Assistant, Alibaba, BMW, Square, eBay, and Capital One.
There’s still one major difference to point out here, though—and that’s how the ecosystems of both these technologies compare. As the more mature technology, the React Native ecosystem is more stable and has a lot more packages available. That’s why it’s still the preferred cross-platform development technology for larger projects. Flutter, on the other hand, can’t be saved by its trendiness and is definitely not as mature as React Native. They just recently hit the stable milestone for their web version last March, and, unlike React Native, they still maintain beta versions of the software on their official site.
With all of that into play, I’ve got to give this one to React Native. Flutter comes very close and it will probably reach the “mature technology” category sooner than expected, but until then, it seems like React Native’s older and more stable community is the winner of this category.
Final React Native vs Flutter Comparative Table
Before finishing up, let’s take a look at all that we’ve learned in a comparative table.
Closing Thoughts
Comparing React Native and Flutter in this article has been particularly difficult, but I hope that the information here can help you in some way or another. After all of this, I do agree with all of the developers I’ve talked to: Flutter is certainly a very interesting technology with a lot of potential, and I can see it growing more throughout the rest of the year.
Nonetheless, I still believe React Native has a place in cross-platform development and that’s not going to change anytime soon. The fact that it’s easier to find senior React Native developers than senior Flutter developers means that most large projects will probably still choose React Native in the near future. Maybe in a year (or less) Flutter will finally reach that “maturity” point and be easier to trust for tech leaders.
For now, I think it’s very exciting that so many people are jumping into the Flutter bandwagon and as CTO of FullStack Labs, I’m also looking forward to working on more Flutter projects with my team. React Native and Flutter are both amazing technologies and I am certain that the future of mobile and cross-platform development lies in them.