v0.8.5
leptos-rs/leptosv0.8.5Jul 21, 2025by gbj
AI Summary
A major feature release introducing WASM code splitting and lazy-loading capabilities for routes and functions.
Key Highlights
- Introduces WASM code-splitting/lazy-loading support.
- Introduces `#[lazy]` macro to convert functions into lazy-loaded async functions.
- Introduces `#[lazy_route]` to split routes into data and view halves.
- Works with nested routing to concurrently load components.
- Includes a dedicated July stream explaining the new features.
New Features
- WASM code-splitting
- `#[lazy]` macro
- `#[lazy_route]` trait
- Concurrent route data and view loading
Full Release Notes
This release includes WASM code-splitting/lazy-loading support, in tandem with the latest `cargo-leptos` release.
You can use the [`lazy_routes`](https://github.com/leptos-rs/leptos/tree/main/examples/lazy_routes) example to understand what this means!
Essentially, though, there are two patterns:
1. Use the `#[lazy]` macro to make any given function lazy
2. Use the `#[lazy_route]` to designate a route with a lazy-loaded view, which is loaded concurrently with the route's data
`#[lazy]` converts a (sync or async) function into a lazy-loaded async function
```rust
#[lazy]
fn deserialize_comments(data: &str) -> Vec<Comment> {
serde_json::from_str(data).unwrap()
}
```
`#[lazy_route]` lets you split routes into a "data" half and a "view" half, which will be concurrently loaded by the router. This works with nested routing: so if you have ViewD and ViewE, then the router will concurrently load D's data, D's (lazy) view, E's data, and E's (lazy) view, before navigating to the page.
```rust
struct ViewD {
data: Resource<Result<Vec<i32>, ServerFnError>>,
}
#[lazy_route]
impl LazyRoute for ViewD {
fn data() -> Self {
Self {
data: Resource::new(|| (), |_| d_data()),
}
}
fn view(this: Self) -> AnyView {
let items = move || {
Suspend::new(async move {
this.data
.await
.unwrap_or_default()
.into_iter()
.map(|item| view! { <li>{item}</li> })
.collect::<Vec<_>>()
})
};
view! {
<p id="page">"View D"</p>
<hr/>
<Suspense fallback=|| view! { <p id="loading">"Loading..."</p> }>
<ul>{items}</ul>
</Suspense>
<Outlet/>
}
.into_any()
}
}
#[server]
async fn d_data() -> Result<Vec<i32>, ServerFnError> {
tokio::time::sleep(std::time::Duration::from_millis(250)).await;
Ok(vec![1, 1, 2, 3, 5, 8, 13])
}
```
Our whole [July stream](https://www.youtube.com/watch?v=2RhDIKfm7VI) was dedicated to the topic, if you want more in depth discussion.
## What's Changed
* Preparing to publish oco_ref 0.2.1 by @martinfrances107 in https://github.com/leptos-rs/leptos/pull/4168
* feat: wasm-splitting library support for future cargo-leptos integration by @gbj in https://github.com/leptos-rs/leptos/pull/3988
**Full Changelog**: https://github.com/leptos-rs/leptos/compare/v0.8.4...v0.8.5