When you’re planning to develop a mobile app the second most important decision you’ll ever make is selecting a technology to use (first being the content of the app)
Ideally you’d want a version of your app for both iOS and Android and so there are really only 3 choices you have in 2021:
1. Develop natively for two platforms, using Kotlin/Java for Android and Swift/Objective C for iOS
2. Use Flutter (made by Google)
3. Use React Native (made by Facebook)
Would creating two separate native apps for iOS and Android be your best bet or should you investigate a hybrid mobile solution to keep a “single code base” for both mobile platforms?
There are multiple considerations you have to keep in mind when making this decision, but before we dive in let’s address the elephant in the room – why only two cross-platform solutions you ask?
Here’s the popularity of the cross-platform technologies over the past two years:
As you can tell, Flutter is the only framework that gained popularity, and React Native is the only one that didn’t lose it. Flutter is probably going to overtake React Native in 2021, so let’s take a deeper dive into the two most popular cross platform mobile development frameworks – React Native and Flutter and compare them to native development.
Let’s take a look at the following 7 aspects of mobile tech stacks:
1. technology behind each
2. popularity
3. development environments
4. ease of use
5. productivity
6. performance
7. scalability
Technology
React Native:
JavaScript/TypeScript running on Node + Expo CLI that runs on the top of React Native providing a layer of abstraction, compiled and packaged by Metro bundler.
Bundled code runs on Javascript VM, which then talks to native device modules via React Native Bridge. If that sounds complicated that’s because it is. There are a lot of moving parts to React Native app, but don’t worry, the framework hides it all from you unless you need to do some complex things in your app. We’ll come back to it.
Notes on React Native threading model:
All JS code runs on JS thread. RN starts main application thread and a bunch of shadow threads as well as custom native modules threads to handle animations. There’s very little developers can do to control the threading model.
Although it has been rumored that React Native compiles and maps JS components into native components, this is not exactly true. React Native never translates your components directly into native components – they are “bridged” by RN bridge, hence the name.
Flutter:
Flutter uses Dart Framework which consists of a variety of available Widgets, recognizes animations and gestures, has Material components baked-in and knows how to render widgets natively.
Dart Framework sits on the top of C++ Engine which manages Dart VM, is aware of frame scheduling, system events and asset resolution.
Since nothing should block UI frame rendering on mobile device, Flutter framework is driven by the Flutter engine frame rendering.
Everything in Flutter is a widget from developer’s perspective. Widgets are bound to native components by Flutter Engine.
Since there’s no JS thread Flutter runs a little faster on the mobile devices.
Native development:
Swift or Objective C for iOS.
Kotlin or Java for Android.
Popularity
React Native – 42% marketshare in 2019 and 2020. Popular mostly because of Javascript, it’s used by Facebook, Instagram, Pinterest, Uber Eats, Walmarts, Tesla, and more.
Flutter – 30% marketshare in 2019, 39% in 2020. Popular because solves most of React Native issues, it’s used by realtor.com, Square, Ebay, CapitalOne, Groupon, Google, Sonos, BMW, etc
Why are these frameworks popular?
They are new and shiny and they look so easy to master and they lure companies into thinking that hiring two teams of iOS and Android developers is twice as expensive as hiring one team of web developers. In reality you’re most likely going to end up with twice the number of web developers than native developers, but of course it all depends on the application scope and business needs.
Too often the company would select one technology just to replace it with another a year later, requiring a complete overhaul of the entire codebase. It usually happens because hybrid (cross-platform) technologies change so quickly that upgrading support libraries becomes a nightmare. Limitations of the selected framework could be solved by another framework next year, etc.
Dev Environment
React Native – javascript or typescript in any text editor but mostly Microsoft Visual Studio Code or Webstorm.
Since React Native framework is very limited in its functionality, the app development usually involves using dozens of third party libraries, some of which are written by a single person and never supported.
React is very difficult to debug since most of the important errors are bubbling up from the depths of the framework and then translated into JS. The stack traces can be unbearable to look at.
Flutter – Dart in Android Studio. Huge collection of rich widgets, native Material design support, no javascript hell. Dart is a lot safer language than JS and a lot easier to debug. The code structure can be unfamiliar to JS developers and it’s not pretty to look at, since almost everything in Flutter is a widget, you end up with a widget inside of a widget inside of a widget and so on – this is called a Widget Tree.
Flutter is easier to set up and it does not require the same amount of third-party libs as more things are available right out-of-the-box
Both platforms support hot reloading, which is a huge help during development. This minimizes the time between making a change and seeing it on the mobile device.
Native – X-Code for iOS. Android Studio for Android. You’ll need Mac for iOS. You won’t need Mac for Android but you might as well.
Ease of use
React Native may seem like the easiest of the bunch because everybody knows JS, but as the application becomes more complicated, Flutter might take the first place. In any case, if you have decided to go with React Native do not use Typescript – it’s a trap!
Since Flutter uses Dart it could require a small initial learning curve, although it is very simple and any Javascript developer can pick it up in a couple of days.
Native development is the most “complicated” of the bunch, so you will absolutely need to hire Android/iOS developers.
Productivity
Productivity depends entirely on the skillset of the development team. If your devs are JS ninjas – then react native will take the cake.
However, since Flutter offers a lot more pre-built widgets and it’s built specifically to create beautiful mobile UIs it must be seriously considered.
Maintenance of React native application can be a pain when multiple third party libs are involved. Most of the upgrades will break parts of the app.
Simple apps are a breeze to write in both React Native and Flutter, with Flutter offering an edge in terms of streamlining the development process, however, as the application becomes more complicated the scales of the tech stack will always tip toward the native development.
Performance
Native will always take the cake here, followed by Flutter, with React Native dragging behind. Lack in mobile performance has been the force behind Facebook’s decision to completely overhaul React Native. They stopped using it for their messenger and re-wrote it in native code.
Due to the threading model described in Technology paragraph above, React Native app will constantly block the UI thread unless a very important attention is paid to the performance. This is extremely difficult to do in RN app.
Now, having said that, it’s important to understand that a poorly written native application will not perform better that a properly written React Native application, so it all depend on the skill level of your development team.
I hope this little overview helps you make the right decision in selecting a mobile technology.
-Joe Berger