Cross-platform frameworks are growing in popularity each year. This stems from the need for companies and organizations to get mobile apps into the hands of users faster. Cross-platform frameworks allow developers to build with one codebase and deploy to multiple targets.
Flutter and React Native are the most popular cross-platform frameworks at the time of writing. We’ll be looking at both head-to-head and at the end, you should have an idea of which one to use in your next mobile app project.
React Native is an open-source mobile application framework developed by Facebook. It started as an internal project before being open-sourced in 2015. Flutter was developed by Google as an SDK for building mobile, web and desktop apps from a single codebase. It was first announced at I/O 2017 and a stable release was later published in November 2018.
React Native is 3 years older so it’s had a first-mover advantage and more time to mature. Flutter has seen rapid growth over the years in terms of popularity and stability to put it on par. For the rest of this article, we’ll compare them using the 6 criteria listed below:
Let’s get into each one in detail.
An important factor to consider when choosing a cross-platform framework is the programming language. This is because if there’s an already existing team, this would influence the framework you decide to go ahead with.
The Flutter documentation provides separate installation guides for macOS, Windows and Linux. To get started on a Mac, you would need to:
cd ~/development unzip ~/Downloads/flutter_macos_2.0.1-stable.zip
Once you are done with those steps, it’s necessary to run the command flutter doctor from your terminal. This ensures that Flutter was set up correctly and also checks for additional dependencies that will be needed for you to develop and run Flutter applications.
To develop Android and iOS apps, you need Android Studio and XCode respectively. The documentation contains instructions on setting up your development environment for the different platforms.
You can create a new Flutter app like so:
flutter create my_flutter_app cd my_flutter_app flutter run
This takes care of installing all the necessary dependencies and scaffolds a boilerplate application for you. flutter run starts the development server which would build and deploys your app to your connected device (Android/iOS).
Flutter supports hot reloading during development so any changes made to the code are reflected on your device. This is great for quickly iterating code and testing ideas. The documentation contains everything you’ll need to develop your app and is relatively easy to follow.
You can develop Flutter apps with Android Studio or VS Code. VS Code has extensions that offer syntax highlighting, linting and code completion. The extension helps to speed up your app development.
React Native has a getting started guide with instructions on how to get up and running with the framework. It recommends using the Expo CLI for developers new to the framework or the React Native CLI for more experienced developers.
To get started with React Native using the Expo CLI tools, install it from your terminal with npm:
npm install -g expo-cli
Create a new project with Expo:
expo init ReactNativeApp
Then run the project like so:
cd ReactNativeApp expo start
Expo builds the project dependencies and starts a development server. When the build is complete, it opens a new tab in your default browser that contains a QR code. The QR code is also outputted in your terminal. To view the app on your devices, you need to download the Expo Go app from Android and iOS. On your Android device, open the Expo Go app to scan the QR code. On your iOS device, use the default camera app to scan the QR code. It takes a few seconds to build the app after which you’ll should see the app on your device.
The default application is very bare and does not contain any useful functionality. As you make changes and save, the changes are immediately reflected on all connected devices. This is due to hot reloading which is also supported by React Native.
Both platforms make it relatively straightforward to get started. Flutter requires you to use a MacBook if you’ll be developing iOS apps. With React Native, you don’t need a MacBook to develop iOS if you are using the Expo CLI. However, if you are using the React Native CLI, then you need a MacBook.
Flutter has a rich variety of UI components designed out of the box. It comes with device API access, navigation and state management built-in. The UI components are also easily customizable to fit any brand identity and style. Apps built with Flutter by default look the same on both iOS and Android.
For example, a Raised Button looks the same on Android and iOS as seen below:
Flutter also allows you to use platform-specific themes (Material Design for Android and Cupertino for iOS) which allows UI elements to look like the native components. When using the respective themes, the raised button looks different on both platforms:
React Native framework comes with basic UI components and device API access. To achieve other things like state management, navigation and/or custom designs, it depends on third-party libraries. React Native as a result has a rich ecosystem of third-party libraries that are used together to build an app.
The button component that comes with React Native can be added to your app with the snippet below:
<Button title="Click me" color="#f194ff" />
By default, React Native UI components look like platform-specific components. The colour "#f194ff" will hence be applied to the button’s background for Android and the button text for iOS as seen below:
To make your app look the same on both platforms, you’ll need to either write your own custom button or use a 3rd party library.
Flutter comes with everything you need to build an app. It has UI components that are easily themeable for custom branding as well as platform-specific designs. With React Native, the basic components use platform-specific styling with a minimal level of customization. To do more, you will need to look into a 3rd party UI library.
Flutter uses the Skia Graphics Library to draw its view. Most work is done on the GPU (Graphics Processing Unit) so UI transitions are quite smooth and deliver 60fps (frames per second). Flutter has most of the native components built into the framework itself so native modules for each platform are shipped with the app. As such, this makes Flutter apps run smoothly when in use.
React Native depends on a bridge to communicate with native modules so this may result in poor performance for apps that heavily rely on native modules. Flutter doesn’t require a bridge and due to its overall architecture, it produces better and consistent performance.
One of the key components of app development when working in teams is testing. Testing ensures that features are working and continue to work after new features are added. Both frameworks have different mechanisms for testing apps which can be seen below.
Flutter comes with an inbuilt set of tools that allow you to perform unit testing, widget testing and integration testing. The Flutter documentation contains examples of how each type of these testing strategies can be carried out and a couple of recipes for different use cases.
The documentation also contains guides on using CI/CD services like Travis CI and Bitrise for testing.
Flutter has good documentation on writing different kinds of tests as well as integrating with popular CI/CD services. React Native also has a good level of testing support but relies on 3rd party services for integration and end-to-end testing.
React Native does not have an official guide for CI/CD support. There are third-party tools that can be used to perform CI/CD operations like Nevercode and GitHub Actions. For CI/CD operations, it depends on third party providers.
React Native provides separate guides for building and deploying Android and iOS apps. For Android deployment, it gives instructions on how to configure Gradle and signing the app. It also gives instructions on shrinking APK size and publishing to various stores that serve android apps.
iOS deployment is also well documented as it shows how to configure the app release, enabling app transport security (ensures all HTTP requests are sent over HTTP), and building the app release. The configuration and build are all done with XCode.
Flutter has a section for continuous integration on the official documentation which points to tutorials to set up CI/CD for Flutter apps. Flutter’s command-line tools also make it easier to set up CI/CD. There are also CI/CD platforms like Bitrise and Codemagic that have official support for Flutter apps.
The Flutter documentation also contains instructions for building and deploying Android and iOS apps.
For Android deployment, you can build your app in two release formats:
1. App bundle (recommended) [flutter build appbundle] 2. APK [flutter build apk --split-per-abi]
It also contains instructions on running the build offline and deploying it to the play store. There are instructions on adding a launcher icon, signing the app, configuring signing in Gradle and shrinking your code with R8.
Both frameworks have well-documented steps for deploying Android and iOS apps to the respective stores. Flutter has better support for DevOps and CI/CD operations.
As can be seen in the previous sections, it’s a tough choice to pick one out of the two frameworks. Each one has its strengths and weaknesses so it really comes down to your use case and available human resources.
Flutter comes with everything you need to take your app from idea to production. So you don’t need to look elsewhere for external plugins.
Either one is an excellent choice so whichever one you choose, you can be confident your users will have a good experience.