Ask HN: Flutter vs. React Native vs. Swift/Kotlin
I have been trying to get my feet wet in mobile development, but I don't know what is the best way to start. So far I've explored Flutter and React Native. There seems to be a steep learning curve when it comes to Flutter.
I'd like to know more from the community
18 comments
[ 4.8 ms ] story [ 43.6 ms ] threadSpecific React Native circumstances and design choices, like the coexistence of alternative Javascript interpreters (e.g. JSC and Hermes), different tools for the same purpose (e.g. npm and yarn), separate organizations (e.g. React vs. React Native vs. the "standard library" vs. certain tools) and radically different code styles (e.g. old class components and new function components that are nicer but without feature parity) add risk and pointless maintenance.
I know the title suggests cross-platform frameworks, but let me give my opinion: go native. For Android, Kotlin + Jetpack Compose. For iOS, Swift + SwiftUI.
Now let me elaborate on my opinion: Cross-platform doesn't work well across devices types. A desktop screen is fundamentally different from a phone screen (one is a big screen controlled with mouse + keyboard, the other is touch on a small screen). All the cross-platform apps I have seen trying to get both Desktop and Mobile are weird in some way: it's just the worst of both worlds.
Now let's say you only want to target Mobile. Then suddenly it's "some cross-platform framework" vs "2 native apps (iOS + Android)". It may seem like cross-platform means "write once", which would be half the time of writing two apps. But that's not the case. Cross-platform is more "write once, debug everywhere". And debugging is not fun, the fun part is to write the app. Kotlin and Jetpack Compose are super cool, Swift and SwiftUI too. Just choose one, and then if your app needs it, learn the other.
Here are a few problems that I have seen with cross-platform frameworks for mobile dev:
- There are huge communities for Android and iOS. Much better than any cross-platform framework. So you are more likely to get help there. - Cross-platform is annoying: develop for Android, then test on iOS and find bugs. Fix them, test on Android and find that your fixes just broke Android. Fix that, and go back testing for iOS. - Cross-platform is a tradeoff: either you have to use what's exactly common between Android/iOS, or you have to do some kind of `if (android) elseif (iOS)` (which sucks). - With cross-platform, as soon as you do something that is not just showing an image and a text, you will hit differences between the platforms: the UI is different between Android and iOS, which one do you want to choose? Permissions work differently. The filesystem works differently. WiFi, Bluetooth, all that. Wanna have a database? You'll quickly need to learn how it works on both platforms. Preferences? Same thing.
In my experience, Flutter is the nicest cross-platform framework I have used. However it's not as nice as native (smaller community, they regularly break the conventions/API (we are at Flutter v3, right?)). Also with Flutter you quickly end up writing plugins where you write your code twice (Android + iOS) and interface it in Dart. So instead of Kotlin + Swift, you now have Kotlin, Swift and Dart, which is not better. Also I am convinced that Flutter will always be a second-class citizen on iOS. If you want to try Flutter, don't do it on Android (because of course that will work better there). Try it on iOS, and see if it is bearable. I found it painful.
As for the web frameworks... IMHO web development should stick to websites :-). Let's write proper Desktop and Mobile apps for Desktop and Mobile, and keep web development for websites.
Conclusion: unless your app is super, super simple, you will be better off with native Android/iOS. And if your app is super, super simple, that's a reason to go native Android/iOS, because that's a simple app to get started!
I don't disagree, but it depends a ton on what the business logic is. If you want to use the filesystem, or the permission system, or WiFi, Bluetooth, etc, then quickly it becomes platform specific.
Say you need some OpenCV or GStreamer, to me it makes sense to use C/C++ (with a nice API to link to Kotlin/Swift) and share that. But many apps don't go that far.
> But I never liked apps that looked like an Android app on iOS or the other way around.
Totally with you here.
One issue that I see is: I need to learn both Kotlin and Swift as opposed to Dart. I wonder how much of a learning curve that would be?
With respect to web frameworks, I totally agree. Web dev is much more fun.
With Flutter, unless everything you want already exists, then you will have to do some Kotlin and Swift (when writing your plugins).
One question I always ask is: do you really need both Android and iOS? Can't you just start with one? If you start with Flutter and then rewrite in Android/iOS, that's 3 apps. If you start with Android and then add iOS, that's 2 apps.
I know people want the cheapest ("I only want to learn Dart"), but the best is usually not the cheapest. IMO, just start with Android/iOS, and continue from there.
This approach makes sense to me. Start with one, and then build the other one. Thanks palata!
It's a pretty cohesive ecosystem, all the build tooling, the package manager, etc comes with the project.
There's relatively little learning of "best practices" because there is mostly one way to do stuff.
People might disagree with me but I find dart a very nice language, feels like more sleek simpler modern Java. Also there is no awkward language conversion with Typescript / Javascript.
Lastly the "Reactive UI" philosophy is pretty similar across the front end frameworks you mentioned.
I haven't used Flutter professionally yet, but, I very much enjoy using it for my personal projects.
Persobally what I enjoyed about kotlin is the maturity of its language and its ecosystem. Literally lots of kotlin libraries in GitHub.
https://kotlinlang.org/docs/multiplatform.html
I understand what RN/Flutter are trying to do but in my opinion it’s a pain to maintain and there are just too many layers that can rot out from under you. Capacitor, on the other hand, is just a bridge from native to JS and your UI is simply HTML/CSS. This also lets your target Web with the same codebase which, while possible in RN/Flutter, is not simple or as maintainable IMHO.
Nothing will beat Swift/Kotlin for platform integration (both in UI and capabilities) but maintaining 2-3 (if you want web as well) codebase is not an easy task for 1 person or even a small team. As far as capabilities, in Capacitor I can also drop down and write native code (it’s 1000x easier than it ever was with Cordova, don’t be scared off if you hated Cordova) if I want so really fully native apps only win on fitting the platform UI better.
I was involved in a project that could only afford updates every so often, and every time I returned to try update packages it was a living nightmare.
Maybe I'll give Capacitor a go.
Toss Fastlane into the mix and local dev, working as a team, and using a build server is a breeze.
I write apps that process hundreds of thousands of dollars through them using Quasar+Capacitor (both taking payment through the app as a customer and using the app to talk to a Bluetooth card reader to process payments as a vendor) and without being able to share a codebase I could never have accomplished this as a solo founder.
- RN is a good place to start if you have React experience. The instant feedback via hot-reloading for UI is quite nice and makes learning fun. Maintenance can be an issue but it's gotten better over the years. Expo is a really great platform, and using Expo helps avoid many maintenance issues as well as helps you stay in JS land (including avoiding Xcode). RN will give you cross-platform out-of-the-box while also increasing exposure to platform-specific issues. In my experience, RN works well a lot of the time but then sometimes you need to deep dive on some tricky issue, which may require native code or a hack.
- Swift is a nice language that'll be most performant + provide the most-true-to-platform iOS UX and there's a lot of nice online resources for learning native iOS. It's a bit tricky right now because there are two native iOS UI frameworks (UIKit, SwiftUI). SwiftUI is the newer approach to iOS dev but you still need to use/interface with UIKit for some things. I'm finding SwiftUI pretty great these days, especially because it allows for Live Previews of UI (similar to RN's live reload); again, this live code<->preview link helps make learning fun. Xcode is a bit of a beast but it's not so bad imo especially for if you aren't on a huge dev team/project.
- I haven't used Flutter much so skipping discussion of that.
- RN vs native can be a divisive issue for a variety of reasons. Both have pros/cons and you can learn a lot from them.
- The best way to start likely depends on where you're at and looking to accomplish. If you really want cross-platform and/or enjoy React, then I'd look at RN. If you're excited about a particular platform, then I'd say go with that native platform's approach.
- Recommended sites/tools: expo for RN (https://expo.dev/), 100 Days of SwiftUI (https://www.hackingwithswift.com/100/swiftui), Stanford's Developing Apps for iOS (https://cs193p.sites.stanford.edu/)