I'm working on a side project that is written in Rust on the backend and the frontend. The frontend component is in Leptos. Our app is about 20kLOC in total, so it takes a little time.

benwis has already written about this

Please see his posts at:

How'd you test this?

Edit a string in a component within our Leptos app back and forth, re-run cargo leptos serve and monitor the times.

What is cargo leptos serve doing?

This confused me initially but it seems like there's basically three steps to the build:

One thing I noticed is it seems to be doing this sequentially, I do wonder if splitting target directories and running the frontend and backend pipelines concurrently might save time.

Starting point

First, for local dev I'm using cargo leptos serve and cargo leptos watch with the default dev/debug build. I don't need an optimized build for local dev unless I'm benchmarking or profiling something and even then the dev build has often been representative, if slower.

The two machines I was testing on were:

The initial times to rebuild were:

The first thing I did was start using mold on Linux, that dropped Linux down to ~7 seconds, putting it on par with macOS. macOS was faster because it uses the fancy new linker Apple introduced out of the box on macOS Sequoia.

With mold on Linux:

Ok, you're using mold. What next?

The next thing I did that helped was enabling opt-level = 3 in the dev profile for all dependencies and build-overrides, but not the project itself. Here's a snippet from our workspace Cargo.toml:


[profile.dev]
opt-level = 0
debug = 1
incremental = true

[profile.dev.package."*"]
opt-level = 3
debug = 2

# For build scripts and proc-macros.
[profile.dev.build-override]
opt-level = 3

debug = 1 for our workspace made it a bit faster than debug = 2. I set the dependencies to debug = 2 because they build once. Our workspace is still opt-level = 0 because that's the fastest option. This applies to both the wasm and the backend build.

This brought the times for both down:

What didn't help?

What might help?

Crate-splitting likely wouldn't help with the build times on the backend part. I profiled rustc for the frontend and backend builds and the backend build is almost 95% link time.

I'm a lot less clear on how the rustc wasm build works but linking didn't explicitly show up there, it looked like it was actually re-doing the same compilation work on each rebuild and wasn't very incremental. According to benwis who was very helpful on the Leptos Discord (Linked on their main site), the bundle size is the main thing that impacts the wasm build. The way to ameliorate this for local dev probably looks like crate splitting and separating components of the website with wasm-split. Probably not worth it for me yet as we don't yet have a neat line of division that would slice off a significant chunk of the wasm payload from the app. There's really just a couple larger main areas of the app and I don't think I can split it horizontally like presentation vs. logic without bridging via JS. I haven't done a lot of frontend in like a decade so there are almost certainly gaps in my understanding here.