3 ms·
This is what I do: - Write the backend in Rust - Write the UI in Flutter - Tie them together using gRPC. You get an API and ability to run client and server
by nu11ptr 3y ago
This is what I do:
- Write the backend in Rust
- Write the UI in Flutter
- Tie them together using gRPC. You get an API and ability to run client and server on different machines as well
I looked at the flutter to rust bridge and started to play with it, but assuming your UI can withstand the slight overhead of gRPC I found it a simpler way to proceed (although I'm not that far in yet)
- dist-epoch 3y ago> You get an API and ability to run client and server on different machines as well So like a web app.
- nu11ptr 3y agoYes, nothing to stop you from substituting Flutter for your frontend of choice including a web-based SPA, but then you would need the gRPC-web extension to call gRPC from a browser. The Rust Tonic crate has this available for the server side.
- monroewalker 3y agoI'm looking at something similar with Go as the backend. Why gRPC instead of a pipe? I started with that as well since it was really easy to set up but that comes with the caveat of requiring network permissions even though it's local to local communication.
- nu11ptr 3y agoPros and cons: with a pipe it will be up to you to create your own message delimiters and protocol, so a pipe is somewhat lower level. You also limit comm. to just that machine, but that may be a pro if that is what you are looking for (omits need for things like username/password or locking to 'localhost'). Lastly, you do not gain an API for your users to consume (if that makes sense for your app - it doesn't always).
- monroewalker 3y agoProtoc actually generates "writeDelimitedMessage" and "readDelimitedMessage" functions for each type. The only thing I needed to add was some buffering on the Dart side to ensure the full message was available. The Go side was able to read the stream and block until input became available
- nu11ptr 3y agoInteresting - so you are using protobuffer encoding over a named pipe?
- monroewalker 3y agoYes but just over stdin/stdout since I'm creating the backend as a subprocess. Not sure if it makes more sense to have the backend be the parent and the flutter app be the subprocess but this is working so far.
- timhh 3y agoI have the same but I wouldn't recommend gRPC. It adds a ton of overhead and complexity that you don't want. Plus you have to deal with all the complexity of Protobuf and the fact that everything becomes `Option<>`. Instead I wrote my own RPC system using Serde and Bincode. Communication is over stdio, that way you can support SSH access extremely easily (like VSCode remote). Unfortunately it was for a company so the code isn't public, but there really wasn't much code to the RPC system at all since you don't need to worry about versioning, authentication, transport, etc. I write a very simple schema language, used Nom to parse it and generate Rust, Typescript and Dart code. The Rust code generation is trivial since you can just `#[derive(Serialize...]`. Typescript / Dart was a bit more complicated (you have to implement Bincode) but it's not very difficult really. By far the most complex thing is trying to integrate with SSH. If you call `ssh` directly then you end up having to parse non-machine-readable prompts and errors and so on. But if you use a proper SSH library then you end up having to implement ssh-agent, read `~/.ssh/config` etc. yourself which isn't fun either.
- nu11ptr 3y agoThis is interesting enough I want to look into it if nothing else than for the geek/cool factor, but the thing I like about gRPC is it gives me layer I can let my client consume as an API (although REST is likely sufficient for this). I actually have an internal API and then two little shim/wrapper layers over the top: one for gRPC and one for REST. My UI consumes the gRPC API. I also want my Rust server to have an independent lifetime from the UI so it can do work in the background. I suspect my use case is just a little different. NOTE: I found this crate that would likely help with Dart codegen of message types: https://crates.io/crates/serde-generate https://crates.io/crates/serde-generate. While stdin/out wouldn't likely work for me, I could use a TCP socket bound to localhost or named pipe as alternative for the transport piece.
- satvikpendem 3y agoHave you seen flutter_rust_bridge? I use that to write business logic in Rust, if I need to use Rust crates. I did that recently for a CRDT library called Automerge.