between a rock and a hard place

If the image is not self-explanatory enough, here’s what it means.

I am the lamb.
Lamb Bobby is stuck between a rock (Flutter) and a rock (React Native)
Lamb Bobby is trying to figure out what Lamb Bobby wants to do.
Lamb Bobby has figured it out and is writing a blog post.

Hybrid apps have always been on my radar. Early on it was Ionic, then it became React Native, and currently, it’s Flutter.

what is a hybrid app

Usually, when someone mentions the word “hybrid” in the software industry, they normally are referring to a cross-platform (iOS and Android) mobile, and maybe web, application that is written with a non-native, web technologies like Javascript.

There’s a decent amount to unpack there, but this lamb won’t go too much into it. I’ll just give a few bullet points and you can take it from there.

  • iOS and Android apps share the same codebase
  • Always some sort of method loading / injecting web code (HTML, CSS, JS) into mobile
  • Considerably slower than native code

current state

I can pretty confidently state that Ionic and React Native are two of the most widely used hybrid app frameworks. I only have had personal experience with React Native so I do have a bit more knowledge about it.

ionic

iconic logo

In short, Ionic is built on top of Cordova which basically spins up a WebView that renders the JS that you write, almost like a web app. In my opinion, it’s very close to a Progressive Web App but better when it comes to compatibility and performance.

Speaking of performance, because you are writing web code to be rendered on a mobile phone, there will always be performance issues, especially with lower-end devices.

react native

react native logo

React Native has gotten a lot of traction in the past few years, mostly because of its performance compared to other hybrid frameworks and it’s a lower barrier of entry for current React and Web developers.

Unlike Ionic, a React Native app actually builds into a native app with native components instead of just a web view. While the developer is writing React component, the UI components are rendered as native UI components. And the javascript that is written outside of the UI components is business logic and is processed through React Native’s javascript engine.

Here’s a great article that goes into how React Native actually works: https://hackernoon.com/understanding-react-native-bridge-concept-e9526066ddb8.

Although React Native is faster than browser-based hybrid frameworks, because of the runtime javascript bridging that goes on, it still suffers a bit when it comes to performance.

flutter

flutter logo

Flutter is relatively new compared to Ionic and React Native. It is also less adopted than the aforementioned frameworks.

Flutter popped up in my news feed right after 1.5 was announced at Google I/O in May. I mostly caught my eye because it was newer and I like new things :D.

Flutter, like Ionic and React Native is pitched as a cross-platform hybrid framework. Web is also mentioned as well as mobile, but I have other thoughts on mobile and web sharing a codebase…

Unlike other frameworks, Flutter uses Dart. Code Mentor did a study on the worst programming languages to learn in 2019. Dart use to be on that list, but with the rise of Flutter, Dart made the biggest comeback from 2018 to 2019 going from 13th place to now 7th (not including the popular languages including Python, Javascript, Java, etc).

Dart supports both Ahead-of-Time (AOT) compiling to native code which makes the combination of Dart and Flutter very fast. However, Dart also has Just-in-Time compiling which allows for fast development time with Flutter’s stateful hot-reload.

With the little exposure of Dart I’ve written, I would say Dart syntax is a mix between Javascript (Typescript) and Java.

Here’s some sample code to compare Typescript with Dart.

1
2
3
4
5
6
7
8
9
10
11
12
13
type AssignmentType = Array<string | number>;
const assignments: Array<AssignmentType> = [
['0x00. Vagrant', 1, 100],
['0x02. vi', 3, 100],
['0x03. Git', 5, 0],
];

const assignmentsAsObject = assignments.map((item: AssignmentType) => {
let [assignmentName, submitAttempts, score] = item;
return {assignmentName, submitAttempts, score};
})

console.log(assignmentsAsObject)

Here’s the same code written in Dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void main() {
// const is single assignment and immutable
const List<List<dynamic>> assignments = [
['0x00. Vagrant', 1, 100],
['0x02. vi', 3, 100],
['0x03. Git', 5, 0],
];

final List<Map<String, dynamic>> assignmentsAsObject = [];

assignments.forEach((assignment) => {
assignmentsAsObject.add({
"assignmentName": assignment[0],
"submitAttempts": assignment[1],
"score": assignment[2]
})
});

print("${assignmentsAsObject}");
}

what is right for me

I have worked with React Native and have been writing javascript for a decent amount of time, so React Native would have been an obvious choice for me.

However, after doing some initial discovery and research, I ended up not using React Native. So I guess I’m not between a rock and a hard place anymore.

To make this section more informative, I’ll come up with a few reasons why Flutter is the way to go for a hybrid app.

very, very fast

Because flutter uses dart, all code is compiled down to native code. No bridge needed during runtime to run javascript code.

Not only is there no bridge, but Dart is also just a faster language than javascript. Here’s a benchmark test between Dart and Node.JS:
https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/dart.html)

Theming

Theming is very important when it comes to a hybrid app. Android and iOS design spec, icons, UI elements are very different. In order to follow the platform design rules, the “theme” of the app should be different on each platform.

Flutter makes it very easy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void main() => runApp(MyApp());

final ThemeData IOSTheme = new ThemeData(
fontFamily: 'SF Pro',
primarySwatch: Colors.green,
primaryColor: Colors.grey[100],
primaryColorBrightness: Brightness.light,
);

final ThemeData AndroidTheme = new ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.lightBlue[800],
accentColor: Colors.cyan[600],
fontFamily: 'Montserrat',
);

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
theme: defaultTargetPlatform == TargetPlatform.iOS
? IOSTheme
: AndroidTheme,
home: SomeWidgetThatIHaventWritten(),
);
}
}

good documentation

Flutter has pretty decent documentation for being a younger framework. I have been able to find everything on flutter’s documentation.

All documentation can be found here: https://flutter.dev/docs

firebase integration

Firebase is Google’s Backend-as-a-Service platform. From what I’ve read, it’s really good even at scale. For my project, I’ll probably be using Firebase so the easy integration was a big plus for me. There setup instructions are pretty minimal and keeping in the Google ecosystem definitely helps.

conclusion

I believe flutter is on track to be a very dominating framework when it comes to hybrid apps, it might even be bigger than React Native in the mobile world.

Flutter provides a near-native experience for the user but with the benefits of being cross-platform. However, because the need to learn a new language along with a framework, the learning curve is quite large and potentially difficult for engineers to learn and get going.

I’m very excited about learning Flutter and Dart, be looking out for deep dives into Flutter and Dart from me soon.