Tauri Mobile – Develop Mobile Apps with JavaScript and Rust
studioterabyte.nl
studioterabyte.nl
Lately, however, I've worked on a Mastodon Client written in Dioxus (https://terhech.de/ebou/). Dioxus runs native Rust code and sends Dom Updates to a Tauri Webview. The difference in Ram and Performance is staggering. Much more lightweight because it uses the System Webview, and much faster because it's not Javascript. I've come to the conclusion that Electron itself is probably fast enough, but its the Javascript that causes it to crawl. (Obviously, my tiny app doesn't compare to Slack, but I've also done some simple-enough Electron Experiments).
And it makes sense: WebKit has seen tremendous amounts of investments to make it as fast as possible. CSS can do GPU based transforms, everything is heavily optimised. I'd venture that WebView rendering is just as fast as native (in the general case). What makes Electron slow is Javascript.
If it's updating a web view then it needs to go through javascript. The fastest rust wasm frameworks are not faster than javascript by any meaningful amount.
Here's the code: https://github.com/DioxusLabs/dioxus/tree/master/packages/in...
This manifests as a snappier experience with less / no GC pauses and a clearer dev experience with a better separation between domains. Rust is just a better language to work with, so it has a certain future-proof quality to it that would pay dividends long term compared to JS in any case.
My suggestion in general not specifically for you is to Profile the slow part of the app and find the problem.
Properly written Javascript running on V8 can be in the same ballpark as WASM and native code as long as you don't torture the GC.
Native code may give you more "optimization headroom" of course, especially with non-standard compiler extensions, but it's not "automatically" drastically faster than JS or WASM (without putting manual effort into optimization, but many of those optimizations would also benefit JS or WASM).
I find useful comparison points are usually React, Preact, and SolidJS: React is fairly slow, but it can do pretty much everything, Preact is React with a lot of parts ripped out to provide a more efficient, slimline version, and SolidJS completely changes the rendering model and is probably the upper limit on how efficient a front-end framework written in Javascript can be.
It's very interesting to compare those with Rust-based frameworks. The big noticeable difference is that all the Rust-based frameworks require significantly more memory, even than React, and ship a lot more total code. However, in terms of performance, they are ringed by Javascript frameworks: SolidJS is by far the fastest framework (although Dioxus is catching up in most areas), and React is by far the slowest.
Obviously a lot of this is to do with how they interact with the DOM. Javascript gets that for free, but Rust and other WASM-based frameworks have to go through a process boundary in order to read or write DOM values. When direct DOM access eventually comes, I suspect we'll see some pretty big changes in these results. But for now, it's pretty clear that the most important thing for optimisation purposes is your application's architecture, rather than the choice of language.
Consider VS Code, software generally considered to be fast enough: every single interaction is handled by a dedicated, hand written, event handler which wherever possible directly modifies existing DOM nodes with the smallest amount of change possible.
This is miles from React. It's what SolidJS aims to do, but the state of the art here seems to be about equivalent to ASM vs Compiled C in 1980: an expert can get miles better performance by dropping down as far as possible in the stack themselves. Not to mention SolidJS forces you into their "lens" of JS, where variables are functions and functions are auto-invoked at the compilers will. And don't even think about refactoring an expression inside JSX to be outside of it or else you'll break all of reactivity. Unless you wrap it in another function, of course.
OTOH I read that and say it's precisely a React issue/bottleneck :)
I do endorse moving from Electron to Tauri tho. I did it for one of my pet projects and I couldn't be happier.
Feels brilliant.
A JS dev who knows generally how to write performant apps can produce some very close to native feeling experiences in WebKit, it simply feels that fast.
Rust meanwhile is a terrible language for UI work. Just like you wouldn’t use assembly for game programming today, or even why you wouldn’t use JS for sensitive systems programming, you don’t use a static compiled, verbose, picky, slow compiling language for a domain that simply demands you have a totally different set of trade offs.
The nature of UI is this: you’re going to iterate a ton, change a ton, you need to be creative and willing to try and throw away experiments as fast as possible, you need the fastest possible feedback cycle between save and hot reload. Your problem space will never be as clear as systems programming. Because the output is visual that time diff between “hmm does this work” and “ok yes/no” needs to be as quick as possible, and you absolutely need to be able to go from idea to output in as quick a time as possible.
This is hugely a function of verbosity, elegance of the libraries and hot reload - JS absolutely crushes Rust along these axis. Meanwhile memory safety isn’t a big concern. But not just that, dynamic languages give you dev tools where you can inspect, edit and test changes and code at runtime and that’s the single biggest productivity boost you’ll find as a frontend dev. These are lessons learned over 20 years of developing for every UI platform under the sun.
The modern web stack is simply going to get you to production with a far higher quality of UI in way, way less time.
I could go on for a lot longer about this topic but suffice it to say: JS is an absolutely incredible language for fronted. It’s set of trade offs match the domain beautifully. I wish it was faster, but WebKit at this point is so much faster and less energy intensive than Blink that I’m extremely happy with app performance in it.
Here's my effort: https://github.com/audulus/rui
On the web I have my app fully running on one side, and my code on the other. I make a change, it shows. Even if it’s inside a deeply nested pane, with some stateful stuff going on. And if things go wrong, I open the console and I inspect everything, change things, run some code, and fix it.
I actually tried SwiftUI on my last app I was making for months before I gave up. It felt like going back to the stone ages.
And that’s Apple putting their full effort behind something with decades of UI stuff already in place!
Not to mention my files kept getting too big for the Swift syntax checker all the time, but I’m sure they can fix that.
This has been said as far back as when Slack engineers explained why they migrated away from system webviews to Electron here on HN.
- Single lightweight binary install and executable (~6 MB), clean uninstall
- Automatic updates (digitally signed, uploaded to a small VM)
- Integrates nicely with SvelteKit and TailwindCSS
- The Rust backend was able to integrate with GTSDK over FFI. The cmake crate made C++ compilation and linking automatic as part of cargo build, provided that a C++ toolchain is available (no problems even on Windows).
- No scary toolchain setup with a load of licenses to review and accept (looking at you, Flutter. I'm a student, not a lawyer. Although perhaps this will also be a thing with Tauri + Android?)
For a small project, I can't recommend it enough. I wouldn't know where to start with a C# or Qt GUI application, especially if I wanted to make it cross-platform.
It'll be interesting to see if it gains any traction in the mobile space. Flutter is great and may be better optimised for certain rendering techniques, such as infinite lists, but sticking with web technologies is a very compelling advantage.
https://github.com/jsuarezruiz/maui-linux/pull/37
The lack of a WASM target is another, although UNO project in the past provided such a target for MAUI's very closely-related predecessor (Xamarin.Forms).
Tauri might be the bees knees and cross platform toolkits are cool but I’m not seeing anything worthwhile in this blogpost.
The project is really about providing the runtime, rather than batteries-included application framework as many mobile platforms provide. Perhaps they are targeting web/rust developers more than native mobile developers?
All the things you would like to see in an example have well-established ways of doing in a web application. Camera access is a good example, where the javascript way of doing is through navigator.getUserMedia(). I imagine it would be supported by Tauri where the underlying browser engine supports it. Tauri provides filesystem access as well, as you don't have that in a web page.
Oh I'm already using Rust in backend so that wouldn't be a big deal. Wonder how well you're able to do GPU / graphics stuff inside webview though? Is WebGPU supported?
I enjoyed your episode on React Native Radio!
And yes, Capacitor apps can target all of those platforms from a single codebase. If you ever need help or have questions feel free to reach out to me on twitter (link in bio)!
I can't imagine it'll be quicker than Flutter development if you 1) don't have strict design requirements, 2) you're pretty much only targeting mobile, 3) you want something that looks good out of the box.
If you already have a webapp and mobile performance is acceptable, I'd consider just doing Capacitor and migrating to Tauri when the mobile ecosystem is in a good place.
Edit: Oh the ionic CEO already recommended it lol
Huh, that always used to be case (back when the iPhone 4 was the latest model). I'm amazed Android devices haven't solved this yet given that even slow android devices must have faster CPUs than an iPhone 4. Perhaps it's a software issue rather than a hardware one...
Apparently it's an issue with Android's webview interaction with accessibility settings.
https://engineering.fb.com/2022/09/30/android/launching-a-ne...
Facebook ships their own webview implementation to solve a couple other webview issues, but that's not really a viable solution for everyone else
For me, it always felt much more difficult to match the native ui behaviours in a web application that it defeats the time won. Especially, when you want to support both Android and iOS.
But on desktop, Tauri is a true gamechanger. Enabling apps to build on the system webview instead of shipping a full grown browser with each installation, that's huge. And now Tauri gets "also does mobile, when you need it", this will make it far more attractive. Not only for apps that might have a mobile use case, but also for developers whose skill investment in Tauri becomes a lot more useful if it can also get applied to mobile.
That's why webview apps are so popular in the first place, because you don't need to deal with the actual Android APIs.
Unfortunately, it hasn't worked out that well for us. Devs aren't liking it, and finding that the shareability of code, particularly because of bluetooth, is making things more difficult than it needs to be.
CTA v3 was released a few hours ago: https://tauri.app/blog/2023/03/01/create-tauri-app-version-3...
All that said, for the novice, why would I use this over dart/flutter, or even one of the huge amount of other JavaScript frameworks?
Effectively, Tauri is like Electron, but bundles the ability to call into Rust land (if you want/need that) and uses the operating system's browser instead of bundling one. The idea is that the apps in Tauri are a lot smaller in mb and use a lot less memory than Electron apps. The con is, of course, you now have to deal with rendering/runtime discrepancies between the different platform browsers. If you're fine with this, and especially if you want to embed rust in your app, go with Tauri. If you want an easier dev experience, don't need to bundle rust (you can but you'll be compiling/loading shared libs), and the bundle size and memory usage isn't a huge concern, go with Electron.
As far as Flutter vs Web tech, that's a whole different question. I've used Flutter here and there and liked it (although I hate Dart) but I really question its long-term staying power. I wonder about accessibility too...can anyone who is more familiar with Flutter way in? Google also has a fascination with killing projects, even ones where "they wouldn't possible kill that" so if you have the time/resources, I'd hedge my bets and learn web tech as well...even knowing vanilla JS/HTML/CSS can get you going pretty far.
So if you've made a bet on Flutter and put a lot into it, I'd say keep going...I wouldn't change everything just yet. But keep the options open and keep exploring too.
As far as web frameworks, I don't think you can go wrong picking one of React, Vue, or Svelte and really investing some time into learning it.
Cordova failed the competition against React Native and Flutter.
Tauri is more like a framework/GUI toolkit for Rust apps.
My first contact with a tauri app is cinny desktop (matrix client) and it's an absolute joy to use. The project source is hardly more than a reference to the source of the web version and some configuration files that make a PWA manifest seem elaborate by comparison.
Otherwise I imagine you could use capacitor from JS? But I see no pitch for how this should be done so far.
it is a wrapper around underlying os webview, basically you load your apps js/page in that webview, if you want to do more native things then you can communicate with that app with ipc (probably tauri_sdk_thing that wraps that ipc )
kinda like electron but donot have to ship chromium browser so less ram usage/ binary size
also since it is a warapper around webview not a lib_chrome_libary like in electron so it has less control in some case otherwise pretty great idea
[0] https://tauri.app [1] https://vuejs.org
The support for all is technically there for all three (and others, like Capacitor) but there's always a few caveats for each and they're rarely the same.
That said, most of the things you mentioned (iOS camera, permissions) don't have any Rust library to work with. So then it is more work because you need to use the native api via FFI. So yeah, I kinda misunderstood your original question. Possible, yes, but by far not as easy as with other solutions that just allow you to write the required functionality with Swift or Kotlin