codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
Notes›mobile

Cross-platform Mobile — Comparing the Candidates

Published 2026-04-28· Updated 2026-05-18·0 views

Cross-platform Mobile — Comparing the Candidates

The desire to build the same app for iOS, Android, and the web from a single codebase has been around for a long time. The tools that emerged as answers picked different approaches in different eras. Some sit on top of a WebView, some call native widgets through a JavaScript bridge, and some draw every pixel onto their own canvas. This post walks through the timeline from PhoneGap to Tauri Mobile and the trade-offs of each candidate.

1. Timeline

Tool First appeared Model
PhoneGap 2009 (Nitobi) WebView + native plugins
Apache Cordova 2011 (PhoneGap donated to ASF) WebView + plugins
Ionic 2013 Cordova / Capacitor + Angular / React / Vue UI
React Native 2015 (Meta) JS bridge + native widgets
NativeScript 2014 JS + direct native access
Xamarin 2011 (acquired by Microsoft 2016) C# + Mono. EoL in 2024
Flutter 2017 (Google) Dart + own canvas (Skia → Impeller)
Capacitor 2019 (Ionic) WebView successor with a cleaner plugin model
Expo 2015 → workflow on top of React Native Managed + EAS Build
.NET MAUI 2022 (Xamarin successor) C# + platform handlers
Kotlin Multiplatform 2018 alpha · 2023 stable Shared Kotlin code, UI via Compose Multiplatform or native
Tauri Mobile 2024 alpha WebView + Rust core. Mobile extension of desktop Tauri

2. Three models

Sit on a WebView — embed the browser engine inside the app and draw the web app on top of it. iOS WKWebView and Android WebView are the stages.

  • Cordova / Capacitor — web app + native plugin bridge.
  • Ionic — Capacitor + UI kit.
  • Tauri Mobile — WebView + Rust core for OS calls.

Strengths — web technologies (HTML, CSS, JS) work as-is. Bundles stay relatively small. Easy to share the same code with desktop and the web. Limits — small differences from native widgets in look and behaviour. Heavy animations and complex gestures can lag. iOS WebView policies and limited push notification support.

JavaScript bridge + native widgets — code written in a JS runtime composes native UI widgets.

  • React Native — JS → native components. The new architecture (Fabric, TurboModules, JSI) reduces bridge overhead.
  • NativeScript — JS calls native APIs directly.

Strengths — native UI look and feel. The React ecosystem (RN). Limits — platform-specific differences still end up as native code branches. Build environments (Xcode, Android SDK) are still required. Library compatibility.

Render directly onto an own canvas — instead of using platform widgets, draw every pixel through a custom graphics engine.

  • Flutter — direct rendering with Skia → Impeller. Material and Cupertino widgets are also drawn internally.

Strengths — pixel-level consistency. 60 / 120 fps animations feel natural. Smooth hot reload. Limits — when the platform introduces new widgets, the framework has to follow. Accessibility and platform integration (system share sheets) need separate implementations. Bundle size is larger than other models.

3. Matrix

Tool Language Rendering Strengths Limits
React Native JS / TS Native widgets React ecosystem · familiar UI Native module compatibility issues
Flutter Dart Own canvas Consistency · performance Large bundle · learning Dart
Capacitor / Ionic JS / TS WebView Shares web code WebView limits
Expo JS / TS On top of RN Build · deploy automation Managed constraints (eased by EAS)
Tauri Mobile JS / TS + Rust WebView Small bundle · Rust safety Mobile is alpha
Kotlin Multiplatform Kotlin Native or Compose Code sharing + native UI option Sharing UI needs extra tooling
.NET MAUI C# Native handlers C# ecosystem · Visual Studio Smaller community
Native (Swift · Kotlin) Swift · Kotlin Native Best integration · accessibility Two codebases

4. Decision factors

Which experience for which user:

  • Are the small look-and-feel differences between the two OSes part of the business value (native or RN).
  • Do consistent pixels matter (Flutter).
  • Want to share code with the web (WebView family).

Team's tech stack:

  • React team — RN.
  • Vue · Angular — Capacitor + Ionic.
  • C# — MAUI.
  • Kotlin / Java — KMP or native.
  • Rust-friendly — Tauri Mobile (alpha, though).

Build · deploy — managed services (Expo EAS, Codemagic, Bitrise) cut down the burden of running build environments. Running native Xcode / Android Studio directly gives more freedom but more infra cost.

Library availability — check the maturity of libraries for core modules like in-app purchases (IAP), push, camera, and Bluetooth.

Accessibility · i18n — own-canvas tools need a separate mapping to the OS accessibility tree. Native widgets are usually stronger here.

5. Operations

iOS build requires macOS — building an iOS app needs Xcode, which only runs on macOS. Windows and Linux developers have options:

  • macOS virtual machine or a Mac mini build server.
  • Cloud build services (EAS, Codemagic, Bitrise, GitHub Actions macOS runner).

Android builds work on Windows, Mac, and Linux alike.

Code signing:

  • iOS — Apple Developer account + certificate + provisioning profile.
  • Android — keystore + Play App Signing.

For details see 03-android-build-apk.

OTA (Over-The-Air) updates — a model that ships JavaScript-only changes to user devices. The scope allowed under App Store and Play Store policies:

  • Expo Updates / EAS Update.
  • CodePush (Microsoft, sunset announced in 2024 → migration needed).
  • expo-updates · self-hosted.

Platform policies allow business-logic tweaks but treat changes to the app's essential function as subject to store review.

6. Common pitfalls

Payments and subscriptions — IAP fee policies of the iOS App Store and Google Play shape the business model.

App store review — common rejection reasons on first submission are privacy policy, test accounts, and feature clarity.

Permission model — iOS and Android differ in permission timing and wording. The flow after a user denial differs too.

Background work — both OSes have aggressive battery policies, so periodic jobs and location often don't run as expected.

Push notifications — iOS background data messages have reliability limits.

Version fragmentation — iOS has fast adoption, Android has wide OS-version diversity. minSdk choice matters.

OS-update compatibility breaks — every year Apple and Google ship new SDKs and some libraries break. Check library maintenance activity.

Localization · regulation — GDPR, personal-data laws, children's data policies (COPPA). Review before a global launch.

Closing thoughts

Cross-platform tooling has different answers for different eras. The core decision is choosing among the WebView, JS-bridge, and own-canvas trade-offs to fit the environment. Team stack + build infra + library availability are the actual weights on the scale. Native is no longer the absolute answer, but it remains the right call where small differences carry business value.

Next

  • flutter-basics
  • android-build-apk

React Native official · Flutter official · Capacitor official · Tauri official · Kotlin Multiplatform · .NET MAUI official · Apple Developer App Store Review · Google Play Policy Center for reference.

More in mobile

All in this category →
  • iOS App Build — Xcode · Signing · TestFlight
  • Android App Build — APK · AAB · Signing
  • Flutter Basics