I've been writing thousands of lines of code of Leptos, a Rust web framework that compiles to WASM in the browser. Here's what the development experience is like.
This project in particular probably won't be open sourced, since it's the admin app for me to update Rust Adventure workshops. I'll likely make other apps instead to do that with.
@chrisbiscardi would you be willing to open-source a stripped down version of this (or similar) app for learning purposes? Maybe with all the working parts connected but with the business logic removed? Something like this, along with this great video, would be a great starter project to study for someone wanting to get up and running with Leptos & MySQL.
@@meowsqueak I will be doing this when I start building workshops for Rust Adventure that teach Leptos. First I need to finish the actual site which is pretty close to done.
I'm actually not sure! I've done a lot of UI work in the past, so probably picked up something somewhere along the line. I definitely didn't install anything specifically for that. The editor is VSCode.
super interesting insights! can you not use macros to write registration like some sort of decorator (which you would do e.g. in python frameworks), that makes a pub sub registry, that rolls out all registration calls? I kind of dislike as a backend dev to see stuff like needing to get the pool in what seems to be a business function and doing a bunch of dB stuff, that looks very much like boiler plate, that you at least would hide in some kind of ORM Manager or other repo pattern, as it kind of looks like this is something that becomes quite a copypaste thing
When the server macro does its code generation, it creates the register_in function, which is responsible for the mechanics behind the register() calls: github.com/leptos-rs/leptos/blob/23f9d537e9d6cafc27ef8fa1299f32b0a0e006c2/server_fn/src/lib.rs#L301-L361. It basically creates an async block and registers it in a hashmap to be called at a later time. The call_fn here is the body of the function you wrote and the hashmap of server functions is lazy_static initialized: github.com/leptos-rs/leptos/blob/23f9d537e9d6cafc27ef8fa1299f32b0a0e006c2/leptos_server/src/lib.rs#L105. I would love to see this registration happen automatically, but that's also just not the way it works today. The DB code is *definitely* copy/paste. In Axum this would live in an extractor, and in my API projects this is where that logic lives. The function argument for the extractor looks like this in Axum, which would eliminate all the boilerplate. DatabaseConnection(conn): DatabaseConnection The issue is that Leptos doesn't integrate well enough with Axum at the moment when it comes to server functions, so you can't use Axum extractors this way in the definition of a server function, you have to pass the pool (or connection or whatnot) in through context/scope. Although from what I hear, that is going to improve soon.
How is the performance of the WASM binaries and compilation on the client for you? Is the WASM being streamed and compiled in steps for you automatically for speed ups? I am pretty sure this isn't server side generated only - but still have limited experience with leptos, so ignore my question if I am not tracking how this works :)
compilation doesn't happen on the client (unless you mean what happens when a regular wasm binary is loaded). The wasm bundle is compiled when the server binary is compiled, at development time or in CI. Then you run the server which does typical server things, and you server the wasm to the client to rehydrate the app client-side. Overall the performance hasn't been noticably worse than any JS-based framework, so I'm happy enough with it.
@@chrisbiscardi ya I was referring to the wasm binary being compiled to machine code by the browser in the standard way all WASM binaries are converted to machine code - I heard that this can hurt performance. Especially if it isnt being streamed and loaded in chunks. But if you havent noticed any perf issues compared to other JS frameworks, that's good enough for me :) . Edit: just wanted to add this only affects initial load times - this is the only concern I have heard with WASM perf.
Hey Chris, thanks for the cool videos. I just wanted to let you know that when I tried signing up to get notified of new posts on Rust Adventure I got a 405 error.
That's totally a choice between you and the client. Only you know what your own (and your client's) appetite for risk is, and whether or not you can fix issues with the framework itself if it comes to that. I might use Leptos for a client, if I was confident that the application could be well formulated in the current iteration of the framework, but there's also the long-term maintenance angle to consider. Does the client have Rust devs that can onboard to maintain the project? how much of their time is going to go towards keeping up with changes for an early framework like Leptos? Is the tradeoff worth it?
Hmm.. I am not well versed in Leptos nor in Rust but why use raw SQL files wth SQLx? Whats the advantage over having some ORM handle it for you (eg. Diesel?) From the file structure alone it looks *really* verbose. Not to mention the current implementation makes for a very static approach.
The raw SQL files are prepared and compile-time checked against the database schema. By keeping them as separate SQL files, I get to take advantage of SQL formatting or any other extensions my editor provides. Its also worth noting that this project is definitely not "optimal", its just a real-world example of a Leptos project. My priorities have definitely been "get the app working/done" and not "make all the *right* choices". For more dynamic applications, diesel might make more sense, but you also then need to include that dynamism on the client-side when building the forms which I wasn't going to do anyway.
on the side-nav by the left, if you scroll more than 100vh you will reach the end, which looks odd. you can fix that by setting its height .side_nav{ min-height = 100vh }
it depends on what the javascript does. It it doesn't interact with the wasm, such as being a standalone web component that instantiates a video player, then it works just fine. custom javascript that you bindgen yourself will also work fine. Third party npm dependencies could require a lot of work, or if they're integrated with a javascript framework like React require being rewritten.
This is the admin app I use for updating www.rustadventure.dev/ workshops, so its not open source. I will have workshops detailing how to work with Leptos on Rust Adventure though, and that code will be available.
I have a video for a whole bunch of different frameworks in this playlist: ru-vid.com/group/PLWtPciJ1UMuBpRg1KbXqxE5WOdY9ze37S and the choices I'm making for this project in this playlist: ru-vid.com/group/PLWtPciJ1UMuARHHLqRVzBiPZSwlqXthgN but no dedicated video comparing Yew and Leptos directly. My personal tldr; is that Yew is more established and I might use it in a situation where I require stability, such as working with a team or a client, and Leptos is much newer and I often am using the main branch commit, so I'm using it partially because I like using emerging frameworks and I think some of the ideas are interesting.
more like the Rust version of a Solid/other framework. The "trpc"-ish part that you're noticing is a feature of Leptos called Server Functions - ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-gr6WHJI8zjQ.html
@@chrisbiscardi But I guess this way of doing this makes the most sense if the api is never intended to be public and only has one client? Asked differently. What approach would you choose when you'd want to build a public facing api?
Building a public API for me would be something else completely. Either a REST style API with Axum or a GraphQL API depending on needs. Leptos server functions are not a user-facing API, and neither is trpc. Server Functions in Leptos are specifically "run this bit of code on the server instead of the client and make it easy to call". That can definitely be used as a shortcut to run some SQL like I'm doing here in this admin app, but it could also be used to add authentication via an http-only cookie to call out to a "real" API, or just process some markdown outside of the browser, etc.
its quite nice! Means I can keep things in .envrc without having to worry about it leaking in my videos, or in my shell history which is also nice for using shell history syncing tools like atuin