or what docs don’t tell you

What is this about

After working quite a long time (in frontend world) with React Native, I decided to try Flutter (it is never good being tied to single framework for long-time). This post will be about installation and environment of RN and Flutter.

What this is not about

This won’t be about reasons why you SHOULD or SHOULD NOT use one, or another framework. We are all adults, and there are always multiple ways to achieve exactly the same goal. Same here.

I will also not talk much about technical details like props, local component state, or ‘global’ state management libraries here like Redux.

What you already know about React Native

Not sure how much time you have, so choose what definition fits you better:

  • for 4 seconds of time: with React Native you can build mobile apps with Javascript
  • for 8 seconds of time: with React Native, you can build apps with Javascript, and share same JS code between Android and iOS
  • for 20 seconds of time: with React Native, you can build apps with Javascript, and share same JS code between Android and iOS, and even web browsers because they all can run in JS Core that is embedded into devices or custom built and shipped with RN (Hermes)
  • for 34 seconds of time: with React Native, you can build apps with Javascript, ̶a̶n̶d̶ ̶s̶h̶a̶r̶e̶ ̶s̶a̶m̶e̶ ̶J̶S̶ ̶c̶o̶d̶e̶ ̶b̶e̶t̶w̶e̶e̶n̶ ̶A̶n̶d̶r̶o̶i̶d̶ ̶a̶n̶d̶ ̶i̶O̶S̶,̶ ̶a̶n̶d̶ ̶e̶v̶e̶n̶ ̶w̶e̶b̶ ̶b̶r̶o̶w̶s̶e̶r̶s̶ ̶b̶e̶c̶a̶u̶s̶e̶ ̶t̶h̶e̶y̶ ̶a̶l̶l̶ ̶c̶a̶n̶ ̶r̶u̶n̶ ̶i̶n̶ ̶J̶S̶ ̶C̶o̶r̶e̶ ̶t̶h̶a̶t̶ ̶i̶s̶ ̶e̶m̶b̶e̶d̶d̶e̶d̶ ̶i̶n̶t̶o̶ ̶d̶e̶v̶i̶c̶e̶s̶ ̶o̶r̶ ̶c̶u̶s̶t̶o̶m̶ ̶b̶u̶i̶l̶t̶ ̶a̶n̶d̶ ̶s̶h̶i̶p̶p̶e̶d̶ ̶w̶i̶t̶h̶ ̶R̶N̶ ̶(̶H̶e̶r̶m̶e̶s̶)̶ because JS can orchestrate native components without bridge (so called Turbomodules architecture)

Cultural shift

As you can see in the picture below - think of it as very simple “mind-map” - things are very similar in both worlds. Try to spend some few seconds trying to pair the bubbles with the same color.

NPM becomes pub.dev, JS becomes Dart, package.json becomes pubspec.yaml, package.lock becomes pubspec.lock. Components become widgets. Not much change.

SDK Installation and creating new projects (for mac)

With React Native:

brew install node
npx react-native init awesomeProject

With Flutter, there is no official brew formula, so you need to download installer from official website or install SDK from github.

The discussion about supporting Flutter installation via brew (or why it is hard) is here.

Languages differences: Javascript, Typescript vs Dart

In short: Typing autocomplete, safety checks, but new data types.

In RN, you work with JS. If you are coming from web dev / or even NodeJS development, you will understand RN quickly. Just remember, that every technology has its cons and pros. JS is not different.

To run the app, JS will be just “bundled”(and minified, etc.). But some RN developers want to have

  • type-checking” (casting String to Int will fail at compile time instead of run-time)
  • autocomplete” (ctrl+ space will show you better hints, what you can call on objects, functions, etc.).

So, they would use Typescript (or less popular solutions like Flow). Learning curve from JS to TS is very, very low (you just put types definition inside JS-looking-like code).

During build phase, Typescript is being compiled into Javascript (because devices / simulators can run JS, and not TS). Then JS bundle is responsible to tell the device, what should be rendered and what should happen when.

JS being interpreted language, it supports one of very popular ways to build things called hot reloading. This means, that you do not have to “build” app and go to coffee machine every time after you write few new lines of code. You see the results in “close-to-real-time” in the real device or simulator.

Moreover, in React, you can mix the code and “markup” with JSX.

From the first look (in eyes of React Native developer), Dart posses similar functionality as TS. You also have autocomplete, type-checking and hot reload. This is achieved by a little bit “unconvential” way of how Flutter works:

  • in dev mode, Dart supports hot reloading, but it comes also with type-checking and autocomplete benefits. Dart in debug mode runs in Dart Virtual Machine (the concept may look similar to RN “debug mode”, where JS runs in Chrome instead of the device JS core, after you turn on debugging)
  • in release mode, Dart is compiled directly to native code (so there is no bridge in comparison to RN)

It is more like Dart is “2-languages-instead of one” behind the scenes. Looking dangerous for you ? Remember, in RN Javascript orchestrates native components.

As it is separate framework, JSX is not present and “widget syntax” / the way how you write components is a little different (topic for next blog posts). See ‘heated’ discussion why JSX is not a way for Flutter here.

Linters

With both languages / frameworks you can enforce syntax-styling. Link for flutter linters: https://pub.dev/packages/linter , and rules you can use: https://dart-lang.github.io/linter/lints/options/options.html

Updating to newer version

I remember, that it was quite a pain in RN, but I did not have the chance to try this so far.

Addons, IDEs

If you are working with React Native, all editors / IDEs you would ever want are VSCode (or your favorite text editor), Android Studio & Xcode. The most time you will probably spent in VS Code & Chrome Dev Tools (for debugging).

Flutter and Dart has better support for debugging so you can debug your apps directly inside VSCode, without another external window for e.g. metro bundler.

Dependencies and versioning

Both frameworks use semantic versioning. If you decide to put ^ everywhere or ‘lock’ your dependencies: it is up to you.

Lean-core

Maybe you already know that from architectural point of view, React Native repo evolved into something that is called “lean-core” in later versions of React Native, and a lot of packages were extracted out of the core into react-community packages. Some were even re-written after some time (e.g. Reanimated library).

The fact is, that you need to integrate more ‘3rd party=like’ libraries for navigation, gestures handling, icons, gradients, etc… And simply, it could take you a little bit of time to find correct versions of packages to glue all these libraries together and get app running. The good is that because RN uses Javascript, sometimes you can also use popular web-dev libraries like momentJS. Just my personal opinion, but I think that RN and its community is more mature in 2021.

On the other side, Flutter repo is monolit. It seems that people are on top of the hype curve with Flutter, as there are currently 8,200 open issues in their repo (and 41k closed). In comparison, RN has 1,126 open issues and (20k closed), but remember that many packages were moved into their own repositories.

The another thing is, that the issues in Flutter repo could look quite serious:

1.) Pasting multiple non-eurpoean unicode characters into TextField drives CPU to 100% and freezes tab
2.) Webview Crashes When Preventing Open in New Tab
3.) iOS 14 crash (Simulator) — Fatal Exception: NSInternalInconsistencyException Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread

NPM vs Pub.dev

As RN packages are hosted in npm, you can host your private / enterprise packages everywhere, where npm repositories are allowed (simply, lot of tools).

This is not straightforward with Flutter and Dart. The official “repository” for Flutter packages supports hosting packages only at machines running in Google-Cloud and was ‘Discountinued’ from 2018 (Link here). Seems like some bad vendor-lock-in trick in my eyes.

There are however, few community alternatives for this - but I have no idea how stable / maintained they are:

unpub | Dart Package
Unpub is a self-hosted private Dart Pub server for Enterprise, with a simple web interface to search and view packages…
rxreader/simple_pub_server
Dart/Flutter private pub server. Contribute to rxreader/simple_pub_server development by creating an account on GitHub.

Build pipelines and CI

NOTE: I am positively biased with Appcenter for React Native builds.

However, it seems that Appcenter is “ignoring Flutter support” so far (the discussion is here ), but you can find scripts for building flutter apps in official appcenter-repo and even couple of blog posts about it, so it should be only matter of time to get things running. If you are already using post-clone.sh scripts, or even Fastlane, this should not be a big problem for you, I guess.

Just to mention, there are also Appcenter’s competitors like bitrise.io, codemagic.io and many others that already support building Flutter apps.

Summary

After playing with Flutter for a few weeks, I cannot get rid of feeling, that Flutter was created after taking look at React Native and then engineers tried to emulate (or copy) similar behavior with Dart. Or another option is, that both RN and Flutter were being created from the same basis.

Will the Flutter’s community push the Flutter that it becomes de facto standard for cross-platform mobile app development in 2021? I personally think it will not, but let’s s see what happens in this year.