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:
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
The discussion about supporting Flutter installation via brew (or why it is hard) is here.
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).
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)
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.
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.
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.
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).
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:
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.
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.