Ábel Putovits

Cross-platform mobile apps

This post is a friendly introduction to the developing landscape of cross-platform mobile apps through an accessible description of two wide-spread frameworks that rely on web technologies: React Native and Apache Cordova. Other perfectly valid and popular choices like Ionic, Flutter or Felgo won’t be included in this post.

Let’s start at the very beginning: why do we care about mobile apps in the first place? According to Finances Online, the global consumer spending in mobile apps was more than $100 billion last year, and the number of smartphone users is forecasted to increase to 3.8 billion in 2021 according to statista.com, so you might as well want to have your meticulously designed logo on all these devices all the time. This could be achieved by using Progressive Web Apps as well, but our opinion is that PWAs enjoy a wider adoption within the circles of technical people than among not-so-technical users, at least for now, in Central Europe.

So, we acknowledged that mobile apps are worth the chat, we want to have our fancy logos on millions of users’ smartphones with an utmost desire, but here comes the interesting part: do we really need to develop (and pay for) two separate apps for Android and IOS devices? Let’s go with the ever so typical (and some say annoying) engineer’s answer: it depends. It always depends on the app itself and the use-cases we want to service, however cross-platform mobile app frameworks can be a great way to reduce development costs and complexity, and there can always be cases when the whole code-base can be reused across both platforms.

Cross-platform mobile app frameworks allow software developers to write native or hybrid mobile apps that run on both Android and IOS using a mostly shared code-base. This basically means that the app that you download from the Apple App Store and the one you get from Google Play Store contain largely the same code. In order to allow this, many of these frameworks rely on web technologies like JavaScript or HTML to provide the app logic and the UI, while native functionalities can be accessed through bindings to platform-specific native libraries implemented by the given framework itself. On a level that’s a tad higher, this means that your app will be written mostly in JavaScript instead of Kotlin or Swift, and this has several pros and cons.

The Good:

  • The code of your app is reusable across both mobile platforms
  • App logic can be reused from your web app (heck, even parts of the UI in some cases)
  • App logic can be reused in your web app 
  • Your app will take less time to develop
  • Your app is still native, can access various sensors, native push notifications, location data, etc.
  • Your app is easy to maintain

The Bad:

  • You sacrifice your cost savings on small but existing performance issues
  • There might come a point when platform-dependent native code still needs to be written
  • The download size of your app will be significantly larger than the pure native one’s

Two of our go-to framework choices are React Native (with extensive use of Expo) and Cordova as they are both exceptional tools for the right job, but let’s discuss the main differences first. Our key differentiators will be the following:

  • Development time: proportional with the development cost
  • Native animations: this has a large impact on user experience
  • Performance: everyone loves a quick, snappy app 
  • Reusability of existing web components: whether you can easily integrate components from existing web pages
  • Support for OTA updates out-of-the-box: Over-The-Air updates are quick because they don’t require a fresh build of your app that needs to be uploaded to the stores
  • Support for AR/VR: whether your app can have Augmented or Virtual Reality features
  • Background code execution: like media playback while the app is in background
  • License: whether the framework is open source and free to use

Access to sensors (like the camera or accelerometer) and support for push notifications won’t be listed as these are supported by all framework choices. Let’s see how React Native and Cordova compare against native apps regarding these properties.

Property \ FrameworkReact NativeApache CordovaNative
Development timelowlowhigh
Truly native UI and animationsyepnopeyep
Performance high to mediummedium to lowhigh, this is our baseline
Web UI reusable (uses CSS)nopeyepnope
OTA updatesyepyepnope
AR / VRyeplimitedyep
Background code executionlimitedlimitedfull support
License*MITApache 2.0Platform-dependent
*License of the given framework, not your app

Though the table above is far from technical, it’s clear that React Native shines in terms of (relative) performance and “nativeness” and that Cordova can be great when an existing web app needs to be embedded into a mobile app format, but let’s dive a tad deeper in the differences. 

Both React Native and Cordova offer a significantly low development time when compared to platform-specific native app development. React Native adheres to the “Learn once, write anywhere” philosophy when speaking in terms of targeted platforms, which means that the same development concepts apply to writing the Android and IOS apps (although in most cases the code can be reused across these). In the case of Cordova, the UI is rendered by a minimal web browser, so the UI will always look exactly the same in the case of all platforms. In case of native apps though, you’ll have to have separate developers writing separate code for each targeted platform, hence the increase in costs.

Performance is the one true caveat of cross-platform frameworks, you’ll never be able to achieve the performance of pure native apps, but you can get extremely close to it. Cordova uses a web browser to render the HTML UI of your app, thus your JS code will be executed on a single thread by default. This means that if it takes 1 second (highly unlikely, unless you’re benchmarking) to compute the next frame of your animation, your app will be stuck for that one second. React Native on the other hand renders your components in a separate UI thread while your logic, state management and event handlers live in a JS thread. Your JS code still runs in a single thread, it just doesn’t have to worry about computing the next frame of your animation. Performance issues are often caused by the communication between these two threads and CPU intensive JS callbacks. The following table demonstrates the startup time of default apps built with each framework.

1. Native2. React Native3. Cordova
The apps above run on the same Android emulator, on the same PC. The fact that they run on an emulator has an extreme negative impact on performance. The recordings were made after 3 warmup runs of each app.

Perhaps the main advantage of Cordova over every other choice that we discuss is the fact that styling is done using CSS, which means that any existing responsive web UI can be reused without a considerable amount of modifications. Imagine it like grabbing your web app and placing it in a mobile app’s shell, extending it with native functionalities. Note that all discussed platforms support WebViews, so simple HTML UIs like terms and conditions pages can be reused in all cases. Although using CSS for styling has it’s pros, it has a significant performance impact when the device’s orientation changes, since the framework has to recompute all dynamic dimensions and positions. 

OTA updates are a way of getting updates to users without them having to install them from the respective stores. In case of React Native and Cordova, your app is written in JS, which means that after an initial build, your app doesn’t need to be recompiled (if the app is not extended with native dependencies). This enables developers to replace app logic on the fly, while the app is running, thus implementing OTA updates. In case of native apps there’s no way to perform this, at least not out-of-the-box. 

Obviously, native apps offer full support for AR and VR features through Google’s ARCore and Apple’s ARKit. Cordova doesn’t have a chance to do so because of its core architecture and principles, but since React Native actually uses native views under the hood, a number of open-source libraries could emerge in order to help build cross-platform AR/VR apps. You can see it in action here. An important thing to mention is that AR and VR are only supported by devices with the proper hardware configuration, and this applies to all cases.

Unfortunately, out-of-the-box support for background code execution is considerably limited in case of cross-platform apps since spawning a JS interpreter in the background has an extreme performance overhead and impact on battery life. This doesn’t mean that you can’t execute background tasks at all though. Both React-Native and Cordova provide APIs for scheduling periodic JS tasks to be run by the OS, but there are a number of caveats when compared to native apps. 

Though our go-to framework for greenfield apps is React Native, the final choice always depends on the actual requirements laid out together with our clients. For an average app, a similar performance and set of features can be achieved and built with either of the aforementioned frameworks.

I hope this post gave you a practical initial introduction to the world of cross-platform mobile apps. If you still have questions or just want to have a good chit-chat about the technical details of these frameworks, let’s grab a coffee, the door is always open at Tűzoltó 66 (entrance from Lenhossék street).