React Native at Prodigi: An Introduction
Why we choose react-native over flutter and the reason behind it
We are a digital brokerage in the insurtech space utilizing technology to connect and protect our customers.
Three months ago, precisely on 3 Oct, 2022, Prodigi decided to create an employee benefits platform and make it a Priority 0, at that time, all benefit engineering teams working in parallel, where Mobile Engineering Team led by Backend Senior Engineer given task to decide between React-Native or Flutter to power our application. At first, we decided to create a sheet to compare react-native and flutter, you can check it out here
ReactNative vs Flutter.xlsx — Google Sheets
Long story short, from various meets, explanations and compare we decided to choose react-native as our main architecture for employee benefits platform, and the detailed reason will be explained here
One Codebase For Many Platform
I think it’s the main reason why we decided to take the path to hybrid mobile application development and choose between react-native or flutter because it’s easier for us to maintain code for many platforms, Android, iOS or Web with small engineering teams, and react-native or flutter can achieve that
Small Engineering Teams & Existing Service
Prodigi has small engineering teams for the mobile developer as front-end (currently 2 engineers), so its great choice to choose hybrid development because it’s not only cost-reducing but can make development much faster; not only that, an average front-end engineer at Prodigi is React Developer, so it’s easy for them to switch between React to React Native and be supporting team, also all current front-end service at Prodigi built with Next, so it’s plus point to using react-native because we can adapt code from existing service to our react-native application such as encryption, data fetching, design pattern, component and many more
Performance & Native Feelings
Both platforms has advantages and disadvantages in terms of performance; many people say RN has trash performance 🤔 than flutter, so let’s dive dig into it
- Achieve 60 FPS & 120 FPS
Both can achieve 60 FPS and 120 FPS in good device, there’s reason why RN developer can’t achieve good performance, first not pay attention to UI-re-render (Memoize method) , not use dedicated component for certain layouts (When to use Virtualized List), not think twice before pick an external library (Deprecated module, not maintained), not use library dedicated to the mobile platform (example: not use firebasejs but use built in sdk), and find the balance between react and native
By default React Native has good performance as well as flutter, but maybe we must expert and know well to profiling performance in react native in best practice, but do you think flutter doesn’t have const in performance? If you look closely, app build with flutter affected by un-smooth momentum scrolling when rendering many image in list, and it can observable well in low-end device, this behavior is rarely seen in react-native because it’s render natively by their respective component either iOS or Android, not like flutter which render all their component with Skia Engine, like rendering shader game
On first run of flutter application, many developer say they encounter janky animation, and that’s because flutter must initial render their shader and caching it, but as we know there’s method to decrease that, Shader compilation jank | Flutter
- Native Feelings
Flutter is not “very performant by default” the web performance is terrible and the iOS scrolling / gestures are v laggy. React Native is performant by default in the sense that everything is native, you have to go out of your way to emulate the platform in React Native. — Evan Bacon
We believe that good application is written in their native language Android in Java/Kotlin, iOS in Swift/Obj C, as well as the user interface, that’s why react-native is more native than flutter.
This, by means, is the experience when we interact with the app, Flutter is rendering their UI with their own renderer (Skia), and react-native rendering their UI with their own native view (iOS & Android), when we compare that two framework and feel the interaction of the app, we can feel the differences, let’s just give a basic example
ScrollView
There’s different feeling when we scrolling item in flutter scrollview, if we scroll it with two finger, flutter accelerate it scrolling speed, it’s totally different with native feeling that iOS and Android has
TextInput
When we declare TextInput in flutter they behave same in android and iOS, but it different in React Native where both TextInput have different padding because they rendering their own Native View and have their own characteristic, and of course their own interactivity
By just looking at this picture we can see how beautifully app that written in native view
This is app that written in Flutter, because they don’t render native view component, so they don’t detected by layout bounds
In my opinion flutter is good choice when you want to develop an application that doesn’t feel native as iOS or Android, like custom UI UX, ex: reflectly, but if you want to achieve fully-native feeling and need a hybrid development, react-native is a way to go
Over The Air Update
Over the air updates is major selling point in React Native, it’s not available in any capacity for flutter users.
Rest of our decision to use react-native can be check in above sheet and this slideshow https://docs.google.com/presentation/d/15RHnWH69LdfsVmzRDeG4aE60lzd3voMYkH6F-uWtxXc/edit?usp=sharing
Development
How we develop our react-native application at Prodigi?
- Use Expo
Expo is like Nextjs of react-native, it makes development more easier and they have maintained SDK that also up to date, also with EAS we can integrate our deployment easier, upgrade our app easily, expo is also one of many communities that have many contributions to react-native ecosystem alongside Software Mansion, Infinite Red, Margelo and many more, and until now the community is kept more growing and contribute to solve issue that happens in react-native ecosystem, don’t forget to fill State of React Native to make react-native more growing
- Pay attention to UI Re-Renders
This is an aspect that every react-native developer must apply, at Prodigi we separate each section as a component and like flutter does in Stateless and Statefull widget, we also define each component as its respective state change, if a component does not have a state change then we wrap it as React.PureComponent, and for component that constantly change, we defined it as React.Component
React memoized hooks are a must at Prodigi, we use useCallback and useMemo to boost performance
- Use Dedicated Component For Certain Layout
Since Prodigi, for now, doesn’t have complex layouts like masonry or list with many images but we already implement method and component to handle list with that complexity issue, for now, screen that has list is claim history with memoized-gesture-handler view item, at first we render 100k item with FlatList without pagination. Actually there’s no issue in rendering that many items, instead blank space when scrolling fast and if we scroll the item and stop in a certain position and quickly tap to the item, app is not responsive for 1s because the viewport still needs to render another component between it, so we decide to use another virtualized layout to handle 100k item, and we decided to use RecyclerView based component, which is FlashList, with that, above issue is solved, rendering in 60fps achieved
For complex list with image, we already implemented image loader component that use image caching algorithm where we use expo-file-system to initial download image from remote server and save it to local cache app directory, and add unique id for caching, and serve it directly if free storage is available, if not available then we fallback to image component either with native component Fresco or with native component Glide/SDWebImage
- New Architecture is a must
Facebook in 2018 started to create new architecture for react-native which is Fabric and TurboModules, at Prodigi we make our priority to use this new arch, this make us to doesn’t rely to much to unmaintained third-party library, for example our component 100% is written from scratch and doesn’t use third-party ui library or deprecated library. You can see detailed comparison between old and new architecture here Analysis of the New React Native Architecture with Results | by Saurabh Shaw | JavaScript in Plain English
- Think twice before pick an external library
As mentioned above in (new architecture is a must), it’s make us to think twice before pick an external library because it will affect our architecture, that’s why we only use library that has certainly maintained like Reanimated, RN Gesture Handler, Expo Modules etc. And if there’s blocker like no community modules that we need in JSI and use old bridge, so we certainly will write our own native modules, this is where new Expo Modules shine Module API Reference — Expo Documentation in the future we will implement that API instead using react native way
- Native first
If we encountered issue related to something that we can’t achieve at Prodigi and we can’t find module that actively maintained, then we must priority native first and make our own native module, for now there’s still no issues, but in the future because we aim to include healths features in our app, we ready to implement this
- Use Library Dedicated To Mobile Platform
At prodigi we don’t rely too much on web api that react have, for example for location we don’t use navigator.getLocation from inside web api react, but instead we use Geolocation native from android or iOS, it’s apply to all platform like image we use Glide/SDWebImage, Firebase we don’t use firebasejs but Firebase SDK Native iOS & Android
- Use Native Animated API
Because we only create ui component from scratch so we are battle-tested to create any component that ui-ux team wants, for that purpose we need to implement animated in each our component, at Prodigi we use native animated API and run it in UI Thread, with that in mind, we can achieve good performance with good experience without interupting JS Thread, you can see the result here:
- Use Hermes Engine
Old react-native is often mocked because their startup time, but with hermes engine startup time is not an issue anymore, we can speed up start up from 3s to just 1s even less than that in good device
- OTA First, Runtime second
We implement OTA to our react-native application with EAS-Updates, so if there’s any modification or minor issue we can deliver it instantly to customer, but if there’s major changes regarding native code so we need to release new runtime version to our apps
Wrap Up
Currently we manage to get 60fps to 120fps in high-end device (pixel 5/6 & Iphone X ) with our current feature and design, and tested it in low-end device got stable result between 50fps and 60fps. We can change between one screen to another screen like sonic, and implement latest tech and architecture, hopefully Prodigi can provided rich content in their explore screen, so we can implement this arch and method, and can deliver great experience to customer using react-native and can overcome many challenges and issue regarding performance and user experience
It’s a pleasure to implement react-native in this insurtech company, although it’s still in development, but we excited to release it soon, for now it’s still early to say that react-native can handle all issue that will rise in this company as development still in progress, we will do our best to deliver best product, and best experience to customer in this mobile apps area.
Thank you for reading! Road to v0.0.1
Next Steps
In the next part of this series, we will deep dive into how development progress happen at Prodigi as well as challenges and future plans