Hi, folks!

Flutter is a technology on hype in mobile development nowadays. New applications are picking it up as a technology of choice, and even old ones are getting rewritten in Flutter, without proper justification though. I would like to provide a strong foundation on what you need to consider if you're going with Cross Platform Native approach and want to understand if Flutter or React-Native makes the most sense for you.

Side-Note: Typically you have 3 choices for a mobile app: Fully native with Kotlin/Swift, Fully web-based(PWA or WebView container) and something in between. We call this option Cross Platform Native, as those are not Web Applications, but Native Apps still using cross-platform approach.

TL; DR

Both technologies provide similar capabilities, however Flutter is a more risky now due to it's immaturity, lack of standard libraries and more narrow community.

Evaluation Criteria

I will not going deep into the cores of both technologies but rather how would you evaluate them from the project perspective and general feasibility. I am going to go through the following:

  • Build & Deployment
  • Libraries & Widgets Availability
  • Tools & Testing
  • Performance
  • Developer Experience
  • Network Capabilities
  • Media Capabilities
  • Security Aspects

Build & Deployment

Being Cross-Platform Native applications both technologies are using the same approach having Android and iOS native parts and include the cross-platform runtimes be it JavaScript or Dart. It can be represented the following way:

Components of Cross Platform Native App 

Build

Both frameworks leverage platform tools for building: Gradle and Xcode build for Android and iOS respectively. From this regard, there is no difference between them and native applications.

There is a difference though within the build time. It may not be important at developer time, however it plays a role during builds on CI and archiving the app in Xcode. I don't have the exact numbers, but "Hello, World" Flutter application builds roughly 3 times faster for me when the same in React-Native. The reason for this is that Flutter bundles as an iOS Framework and React-Native gets recompiled from sources.

Dependency Management

๐Ÿ‘ React-Native uses NPM packages to include the dependencies of the application including React-Native itself. Aside from npm, you can use yarn to install and manage your dependencies. For the dependencies which require Kotlin/Java/Swift/Objective-C code those parts are linked using gradle modules and CocoaPods packages. React-Native includes an auto-linking feature which allows to avoid altering the gradle and Podspec files automatically without a requirement to do it manually.

๐Ÿ‘ Flutter uses the dart package manager also known as pub tool. The packages are shipped in the form of source code and get compiled during the main app compilation. As well as in RN those packages can have native dependencies, but in this case you may need to add those dependencies manually into gradle and Podspec files. You can also use the unpublished packages by linking them to a folder or a git repo right away.

Deployment

The architecture above means that you need to bundle or compile the shared code, include it in the final apk/ipa and ship the result. The pipeline may look as following:

Mobile app deployment pipeline

There are still differences though. React-Native supports a Code Push technology allowing to push JS code updates without republishing the apk/ipa due to the fact that React-Native runs JS code bundle in runtime and able to replace it. This may be considered as a security concern which being taken into account led the Flutter team not to support this feature at all.

Libraries & Widgets Availability

Library with hanging bulbs
Photo by ๐Ÿ‡ธ๐Ÿ‡ฎ Janko Ferliฤ / Unsplash

Libraries and 3rd party components

๐Ÿ‘ React-Native being in the market for more than 5 years dispose tons of libraries for different cases starting with push notifications, video playback and material components ending up with camera(including Firebase ML Kit) and Apple HealthKit and Google Fit integrations.

There is a curated list of high quality 3rd party components you can leverage in your application called awesome-react-native.

๐Ÿ‘ React-Native also heavily benefits from being based on React and ability to use the libraries built for React without web specific like Redux or axios or bring modern features like React Hooks.

๐Ÿ‘Ž Flutter is here for only 2 years. Still it becomes more popular every day causing the enthusiasts to develop libraries for it. Some navigations solutions already exist, sliders, UI components, Firebase integrations and so on. However a lot of capabilities are still in the base stage.

There is also a curated list of libraries for flutter called awesome-flutter. You can notice it is 3 times less long than for RN. I understand this is not a very fair metric but provides the perspective.

Also, Dart is rarely used outside Flutter, and the Flutter itself is not based on any other library of framework which also doesn't help with ready to use components or approaches.

Widgets

๐Ÿ‘ React-Native has a big library of UI components: Calendars, Date Pickers, Buttons, Material Components, SVG support and many more.

๐Ÿ‘Ž Flutter goes with Material and Cupertino components out of the box. As for the 3rd party libraries in general, the UI library is in its early stage. You may have not encountered a lack of components, however the number of components libraries is way bigger for React-Native. This will change in future as more and more developers start working with Flutters. ย 

Tools & Testing

My take on this topic is that there is a parity between the technologies. Both stacks include:

Performance

Performance should be considered from the several perspectives:

  • View layer performance
  • Native Interop
  • Startup time

View layer performance

๐Ÿ‘Ž React-Native uses Native Views of each platform and communicate the events inside out through JavaScript. This affects the view layer performance, however 60 fps are still achievable, though the performance depends on the OS Version and the device itself.

๐Ÿ‘ Flutter on the other hand renders everything using their own 2D Engine named Skia avoiding any bridge between View and other code. This makes the View layer blazingly fast. It still may have issues on iOS for example, but this issue should be resolved with recent Metal support. ย 

Native Interop

I can't say anything nowadays as this requires microbenchmarking of both solutions on different devices. Maybe somebody can do this research and write a separate article.

Startup time

๐Ÿ‘Ž React-Native has an issue with this. The startup time is a common concern if you strive for excellence. RN should load the JS VM and then the JS bundle. Especially with Android it becomes a hard task. React-Native version 0.60 brings the support for Hermes: a new experimental JS VM for Android which is meant to load fast. ย 

๐Ÿ‘ Flutter seems to already solve this problem.

Developer Experience

๐Ÿ‘Ž React-Native provides a feature called Fast Refresh, allowing to see the changes instantly on the simulator/emulator or a real device which reduces the feedback cycle to virtually zero which is great compared to native development.

The development is typically done with VSCode or WebStorm(those are the most popular tools). Both includes capabilities to run and debug the code, run tests, see coverage and provide autocomplete. In my personal experience the autocomplete is limited(I think due ot JavaScript itself) and I felt back to run the builds either with

npx react-native run-ios

or through Xcode because run through WebStorm was very unstable. Also the packager itself was crashing from time to time.

The typical debugging experience is launching Google Chrome and using it's Console which is suboptimal.

React Native Fast Refresh

๐Ÿ‘ Flutter has awesome developer experience. Being a Google product allows to integrate the IDE(Android Studio, but I prefer IntelliJ Idea as more stable) with the toolchain. The Hot Reload is pretty much the same as Fast Refresh but even better. Autocomplete works very well as Dart is statically typed so IDE support is great. Flutter tool also provides a very detailed and clear reason for errors, so they are easy to debug. The debugger in the IDE works very good as well. VSCode also supports Flutter, but lacks the debugging and VCS features.

Network Capabilities

๐Ÿ‘ React-Native provides a basic http(s) with fetch() polyfill, built-in WebSockets support and rich clients with axios(another example of pure js library!) and rn-fetch-blob. ย React-Native also parses json for you out-of-the-box because it's JavaScript. It also means you can generate your types using Open Api.

๐Ÿ‘Ž Flutter has only a built-in http(s) and WebSockets clients. Axios client is under development(I even think of building my own, say "fluxios" )). JSON parsing should be done manually. Open API support exists, but wasn't updated for 15 month. Update: there is a powerful Dio package.

Media Capabilities

Both platform rely heavily on the underlying platforms. No framework on top of the Android/iOS themselves are not trying to bring something out of mind but rather use the media components available in the system. The question here is how well the native capabilities are supported.

๐Ÿ‘ React-Native supports both Audio and Video playback & recording. For example you can show a video in different formats(basically all supported by ExoPlayer(Android) and AVPlayer(iOS)), show the controls for seeking, looping etc. ย You can also display SRT and VTT subtitles for the video out of the box. This comes with the components like react-native-video, react-native-video-controls and others.

๐Ÿ‘Ž Flutter basically has only video_player package to play a video. It's 1.0 version is still pending(May 2020) and can also show all the video formats mobile OSes provide, but only is able to show SRT subtitles. VTT subtitles are not on the roadmap. For the basic controls you need to use chewie package.

Security Aspects

๐Ÿ‘Ž React-Native bundles the js code and brings it within itself. You can always extract the bundle and reverse engineer it. This sounds like a major concern.

๐Ÿ‘ Flutter is harder to reverse engineer as it gets compile ahead of time into native code for target architecture. ย 

Resume

As always your choice depends on the Non-Functional requirements. What you need to consider is the following:

  • Lack of libraries for Flutter
  • Teaching Dart to new developers as there are no such developers on the market
  • Poor media capabilities for Flutter
  • Longer startup time for React-Native
  • Poorer security for React-Native

P.S. If you liked the article, please do not hesitate to share it and follow me on Twitter to see when a new article goes live.