Flutter or React Native, a cross-platform dilemma - How they work - (Part 3)
Welcome to the third part of this article series about React Native and Flutter. In the latest episode, we have talked about User Interfaces and how to build them in the two frameworks. In this article, we’ll go deeper under the hoods to understand how things work. But I will not go deeper with lot’s of details and implementation things, because I want to make you understand how the thing works at a high level. If you are interested to go deeper, I will leave across the article some links for further information.
But, before moving on, I suggest you read the previous articles of the series if you have lost them.
Flutter instead works in a completely different way. In fact, all the widgets are managed and rendered using an engine (written in C++). In the figure below, you can see a representation of the Flutter Engine.
As you can see, there is a block called “Skia”. Skia is an open-source 2D graphic library managed by Google and you may already know about it, because it is used by Chrome, Chrome OS, Android, Firefox and many others. And in Flutter, Skia is responsible for rendering the widgets in a canvas. In this way, there isn’t a continuous communication between the “cross-platform technology” and the native part and everything is faster. Moreover, all the Dart code is compiled to native code to speed things up. be aware that the compilation to native code is performed only for production build and for this reason debug builds can be slower.
Common interesting features
And finally, I want to conclude with some interesting features that both Flutter and React Native have.
The first one is “Hot Reload”, i.e. the capability of loading new changes without recompiling the entire application again. This feature is really really useful for example when you are trying different colors, font sizes, etc; waiting for an entire recompilation for these little changes it would be such a pain. In Flutter this feature is possible thanks to a combination of Ahead-of-time (AOT) and Just-in-time compilation. In fact, as mentioned earlier, Flutter generates machine code for production builds. For the debug builds instead, there is a virtual machine that can receive the new code, replace the old one and maintain the state. Here you can find more information about hot reload in Flutter.
In React Native instead, the Hot Reload is built on top of Hot Module Replacement by Webpack. Basically there is a runtime included in the app that receives the new code and it replaces the old one. If you are interested in the details, I suggest you read this blog post from Facebook.
Update only components/widgets that have changed
Both Flutter and React Native are declarative frameworks. This means that we define the current UI state (e.g. a loading state, an error state, etc.) and the framework manages the state changes. To achieve these, the framework creates an abstract representation of the UI and when the UI state has changed, it builds a new representation that it will be compared and to the previous one and only the differences will be rendered.
To achieve these, React Native uses a Virtual DOM as UI representation (as you can see in the image below, basically a JSON file that contains all the information about the UI component).
Then the different DOMs are compared using reconciliation, a heuristic diff comparison algorithm. For more information about it, you can give a look to the React documentation.
Flutter instead builds an Element Tree as a representation of the UI but instead, it does not use a tree-diffing algorithm to find the differences but instead, for each element of the UI the children list are examined independently.
For more information about it, you can give a look to the Flutter documentation.
With Flutter and React Native, you can create a view, a screen or even an entire feature and then integrate it in an existing native application. This possibility can be really useful for example for very fast-evolving features or for an MVP feature that we are not so sure that it will be useful or even for a feature that will not be used so much. So it really depends on your situation but I can assure you that is not a crazy thing and maybe in the future, you could find yourself in this situation.
react-native bundle \ --verbose \ --platform android \ --dev false --entry-file index.js \ --bundle-output your-project/app/src/main/assets/index.android.bundle \ --assets-dest your-project/app/src/main/res \ --sourcemap-output utils/android.main.bundle.map
For more information, please visit the official documentation.
Also in Flutter, you have to define a container view in your native application but instead, you don’t need to write a kilometric command to generate bundle: you just add the Flutter project directly from Android Studio and that’s it! ( for iOs there is more work to do: you have to add a Flutter SDK hook to the CocoaPods and to Xcode build phase ).
Again, for more information, I suggest you read the official documentation
And we have reached the end of this journey through the internals of Flutter and React Native. I understand that I went through lots of things in this article but I think that it’s necessary to know a little bit about how things work if you choose and work with these frameworks. In fact, the way how these frameworks work can affect your product.
In the next (final) episode, we’ll wrap things up and I’ll help you resolve the dilemma!