Releases: leptos-rs/leptos
v0.8.6
Just a patch release, mostly to support #[server] #[lazy]
for lazy server functions.
Going forward, patch releases for various crates will have version numbers that are not coupled to one another, and will only be bumped when they've actually changed; so this release is 0.8.6 for leptos
, leptos_macro
, and server_fn_macro
, but does not arbitrarily bump other packages that haven't changed.
See 0.8.5 for notes on WASM splitting.
What's Changed
- fix(CI): remove autofix CI timeout by @sabify in #4173
- chore: bump wasm-split version numbers by @gbj in #4170
- chore(deps): bump redox_syscall from 0.5.14 to 0.5.15 in the rust-dependencies group by @dependabot[bot] in #4171
- feat: allow lazy server functions by @gbj in #4169
- fix: support file hashing when using lazy loading by @gbj in #4182
- Enhancing members’ versioning by @sabify in #4172
- A few pieces of lazy island clean-up by @gbj in #4186
Full Changelog: v0.8.5...v0.8.6
v0.8.5: WASM code splitting released!
This release includes WASM code-splitting/lazy-loading support, in tandem with the latest cargo-leptos
release.
You can use the lazy_routes
example to understand what this means!
Essentially, though, there are two patterns:
- Use the
#[lazy]
macro to make any given function lazy - 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
#[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.
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 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 #4168
- feat: wasm-splitting library support for future cargo-leptos integration by @gbj in #3988
Full Changelog: v0.8.4...v0.8.5
v0.8.4
There are some small bugfixes in here, as well as improvements to the hot-reloading code. This is mostly intended to be a sort of "last patch" before merging the code-splitting changes in #3988, so that there is a patch people can pin to in case those inadvertently introduce any regressions.
What's Changed
- fix: bump workspace dependency versions (closes #4146) by @gbj in #4149
- Version updates + stable hot-reloading by @gbj in #4161
- feat: support conversion from signals and optional get extension for TextProp by @mahdi739 in #4159
- docs: add warning for reading hash on the server by @TERRORW0LF in #4158
- fix: three hot-reloading bugs ( closes #3191 ) by @shadr in #4154
- chore(deps): bump the rust-dependencies group across 1 directory with 15 updates by @dependabot[bot] in #4152
- We're kinda prod-ready by @rakshith-ravi in #4148
- chore: examples - bumped version numbers for sqlx and this error. by @martinfrances107 in #4126
- fix(CI): check latest commit for version release instead of version tag by @sabify in #4150
- Disable default features for Actix by @dbanty in #3921
- feat: add
debug_log!
,debug_error!
,console_debug_log
andconsole_debug_error
by @mahdi739 in #4160 - fix(hot-reload): implement Myers diffing algorithm by @shadr in #4162
- fix(hot-reload): hot-reload stops working when number of views changes in a file + small fixes by @shadr in #4167
New Contributors
Full Changelog: v0.8.3...v0.8.4
v0.8.3
This is a minor patch release. It does include a significant re-write of how ownership/context work with nested routes (#4091). This should close a number of bugs. However, it's always possible that changes like this introduce regressions. Please test to see whether you have any issues with context and nested routing, and let me know. (We have a new regression
example set up to add e2e regression tests for issues going forward.)
What's Changed
- Remove unnecessary "crate::" prefix in a documentation example. by @eroman-code in #3952
- Fix deprecated parameters js warning by @matchish in #3956
- fix: correct doc comment for
SsrMode::PartiallyBlocked
(closes #3963) by @marcuswhybrow in #3964 - fix: add namespace to g in svg portals (closes #3958) by @uber5001 in #3960
- fix: allow rebuilding
Vec<_>
before it is mounted (closes #3962) by @gbj in #3966 - chore: unify all deps with min occurrences of 2 by @sabify in #3854
- chore: upgrade rand and getrandom by @sabify in #3840
- fix: render identical branch structure for out-of-order and async streaming of Suspense (closes #3970) by @gbj in #3977
- fix: remove non-existent feature dep in leptos_macro by @sabify in #3985
- feat: add missing
Resource::write()
and similar functions (see #3959) by @gbj in #3984 - Fix spelling typos. by @eroman-code in #3965
- fix: meta tags not properly rendered inside synchronously-available Suspend (closes #3976) by @gbj in #3991
- fix: smooshed static segments no longer matches the path #3968 by @mskorkowski in #3973
- Provide error message if file hashing is enabled but no hash file is … by @Bytekeeper in #3990
- fix: forward missing lint attributes passed to
#[component]
macro by @mondeja in #3989 - fix: don't use
Arc::ptr_eq
for string comparison (closes #3983) by @gbj in #3994 - docs: document
#[prop(default = ...)]
and#[prop(name = ...)]
by @mondeja in #4003 - Make handle_response_inner public to be used in custom file_and_error (see #3996) by @NCura in #3998
- Fix context issues with nesting routing by @gbj in #4015
- Implement AttributeValue for Cow<'_, str> by @sgued in #4013
- fix: fix
<select>
value by ensuring HTML children are mounted before setting attributes (closes #4005) by @gbj in #4008 - Minor: bump rkyv to 0.8.10. by @martinfrances107 in #4018
- remove unnecessary where-clauses by @lcnr in #4023
- Fix typo by @saikatdas0790 in #4025
- Update
session_auth_axum
example by @gbj in #4033 - fix: allow multiple
#[middleware]
macros (closes #4029) by @gbj in #4048 - fix: suppress false-positive warning when adding children to a
<For/>
that is not currently mounted (closes #3385) by @gbj in #4050 - fix: allow nested untracked reads without false positives (closes #4032) by @gbj in #4049
- chore: Fix issue template check boxes by @JosiahParry in #4031
- fix: do not track anything inside the
async
block of aResource
(closes #4060) by @gbj in #4061 - Tests for #4061 by @metatoaster in #4064
- fix: hygiene on
view
macro. by @metatoaster in #4071 - fix: memory leak introduced by #4015 by @gbj in #4065
- docs: update Tauri project to Leptos v0.8.2 by @mondeja in #4020
- feat(CI): add checking minimal-versions on release by @sabify in #3987
- Bugfixes to
reactive_stores
by @elias098 in #4056 - Fix unresolved path in server side redirect by @TERRORW0LF in #4074
- feat: allow dereferencing
LocalResource
to anAsyncDerived
(closes #4063) by @gbj in #4077 - Fix updates to static class names by @gbj in #4078
- fix: don't render a comment node for
()
attributes intemplate
(closes #4079) by @gbj in #4080 - Remove unnecessary Option wrapping by @mohe2015 in #4035
- Removed crate once_cell by @martinfrances107 in #4083
- Fix compilation because of concurrent conflicting change by @mohe2015 in #4090
- Use remove_event_listener_with_callback_and_bool when capturing listener by @foldedwave in #4082
- feat: impl
IntoFragment
forAnyView
by @gbj in #4087 - docs: add document on adding
class
and other attributes to<A/>
component by @gbj in #4086 - Add template cache for dom. by @bicarlsen in #4099
- Add inert svg elements. by @bicarlsen in #4085
- chore(deps): bump autofix-ci/action from 1.3.1 to 1.3.2 by @dependabot[bot] in #4072
- enhance: handle ../ in aria-current for A tags by @TERRORW0LF in #4051
- [fix] Update
svg::InertElement
fordom
cache. by @bicarlsen in #4100 - Create
svg::InertElement
templates in SVG namespace. by @bicarlsen in #4104 - feat: add method
take
for BrowserFormData by @veigaribo in #4102 - fix: correctly provide context via nested outlets (closes #4088) by @gbj in #4091
- chore: remove now-unused
join_contexts
API by @gbj in #4113 - A place to put e2e tests for regression, plus reporting issue caused by #4091. by @metatoaster in #4114
- chore bump syn and tokio-tungsenite. by @martinfrances107 in #4117
- Use inert_element for top level elements. by @bicarlsen in #4109
- chore(deps): bump the rust-dependencies group across 1 directory with 18 updates by @dependabot[bot] in #4110
- fix: disable InertElement when global class is provided (closes #4116) by @gbj in #4119
- chore: Respond to updated clippy rules by @martinfrances107 in #4120
- Add an example to show server_fn is capable to serve on Cloudflare Workers by @ryo33 in #4052
- Clean up nested routing ownership and add regression tests by @gbj in #4115
- fix(examples): remove redundant cf-worker example by @sabify in #4140
- Fixes #4136: Compile time errors while deriving store by @mskorkowski in #4142
New Contributors
- @matchish made their first contribution in #3956
- @uber5001 made their first contribution in #3960
- @mskorkowski made their first contribution in #3973
- @Bytekeeper made their first contribution in #3990
- @lcnr made their first contribution in #4023
- @JosiahParry made their first contribution in #4031
- @elias098 made their first contribution in #4056
- @mohe2015 made their first contribution in #4035
- @foldedwave made their first contribution in #4082
Full Changelog: v0.8.2...v0.8.3
v0.8.2
For 0.8 release notes in general, see 0.8.0
. This patch release mostly addresses a bad issue with hydrating <Stylesheet/>
and other meta components. (See #3945 #3946)
What's Changed
- fix: correct order of meta content relative to surrounding tags (closes #3945) by @gbj in #3950
- Fix cargo-leptos stylesheet caching (#3927) by @luxalpa in #3947
Full Changelog: v0.8.1...v0.8.2
v0.8.1
For 0.8 release notes in general, see 0.8.0
. This patch release is mostly just a bunch of bugfixes for issues raised or fixed since then.
What's Changed
- fix(docs): correct panic message in copied example code by @LeoniePhiline in #3911
- fix: allow nested Suspense > ErrorBoundary > Suspense (closes #3908) by @gbj in #3913
- fix: correct issues with
StaticVec::rebuild()
by aligning implementation withVec::rebuild()
(closes #3906) by @gbj in #3920 - fix: clear and re-throw errors in correct order by @gbj in #3923
- fix(CI): prevent regreession from nightly clippy in autofix by @sabify in #3917
- Fix some typos in the documentation/examples for reactive store. by @eroman-code in #3924
- feat: check the
counter_isomorphic
release build with the leptos_debuginfo by @sabify in #3918 - fix: ensure that nested children of a
RenderEffect
are dropped while dropped aRenderEffect
(closes #3922) by @gbj in #3926 - fix: correctly provide context through islands to children (closes #3928) by @gbj in #3933
- reactive_stores: implement PartialEq and Eq for Store by @wrl in #3915
- fix: use a runtime check rather than an unnecessary
Either
to determine how to render islands (see #3896; closes #3929) by @gbj in #3938 - fix: remove extra marker node after text node when marking a branch (closes #3936) by @gbj in #3940
- feat: add
.map()
and.and_then()
onLocalResource
by @gbj in #3941 - Some
islands_router
improvements by @gbj in #3942
New Contributors
- @LeoniePhiline made their first contribution in #3911
- @eroman-code made their first contribution in #3924
- @wrl made their first contribution in #3915
Full Changelog: v0.8.0...v0.8.1
v0.8.0
*Changelog relative to 0.7.8
. *
0.8 has been planned for a while, primarily to accommodate small changes that arose during the course of testing and adopting 0.7, most of which are technically semver-breaking but should not meaningfully affect user code. I think it's a significant QOL and user DX upgrade and I'm excited to properly release it.
Noteworthy features:
- Axum 0.8 support. (This alone required a major version bump, as we reexport some Axum types.) (thanks to @sabify for the migration work here)
- Significant improvements to compile times when using
--cfg=erase_components
, which is useful as a dev-mode optimization (thanks to @zakstucke) This is the default setting forcargo-leptos
with its latest release, and can be set up manually for use with Trunk. (See docs here.) - Support for the new
islands-router
features that allow a client-side routing experience while using islands (see theislands_router
example) (this one was me) - Improved server function error handling by allowing you to use any type that implements
FromServerFnError
rather than being constrained to useServerFnError
(see #3274). (Note: This will require changes if you're using a custom error type, but should be a better experience.) (thanks to @ryo33) - Support for creating WebSockets via server fns (thanks to @ealmloff)
- Changes to make custom errors significantly more ergonomic when using server functions
LocalResource
no longer exposes aSendWrapper
in the API for the types it returns. (Breaking change: this will require removing some.as_deref()
and so on when usingLocalResource
, but ends up with a much better API.)- Significantly improved DX/bugfixes for thread-local Actions.
As you can see this was a real team effort and, as always, I'm grateful for the contributions of everyone named above, and all those who made commits below.
WebSocket Example
The WebSocket support is particularly exciting, as it allows you to call server functions using the default Rust Stream
trait from the futures
crate, and have those streams send messages over websockets without you needing to know anything about that process. The API landed in a place that feels like a great extension of the "server function" abstraction in which you can make HTTP requests as if they were ordinary async calls. The websocket stuff doesn't integrate directly with Resources/SSR (which make more sense for one-shot things) but is really easy to use:
use server_fn::{codec::JsonEncoding, BoxedStream, ServerFnError, Websocket};
// The websocket protocol can be used on any server function that accepts and returns a [`BoxedStream`]
// with items that can be encoded by the input and output encoding generics.
//
// In this case, the input and output encodings are [`Json`] and [`Json`], respectively which requires
// the items to implement [`Serialize`] and [`Deserialize`].
#[server(protocol = Websocket<JsonEncoding, JsonEncoding>)]
async fn echo_websocket(
input: BoxedStream<String, ServerFnError>,
) -> Result<BoxedStream<String, ServerFnError>, ServerFnError> {
use futures::channel::mpsc;
use futures::{SinkExt, StreamExt};
let mut input = input; // FIXME :-) server fn fields should pass mut through to destructure
// create a channel of outgoing websocket messages
// we'll return rx, so sending a message to tx will send a message to the client via the websocket
let (mut tx, rx) = mpsc::channel(1);
// spawn a task to listen to the input stream of messages coming in over the websocket
tokio::spawn(async move {
while let Some(msg) = input.next().await {
// do some work on each message, and then send our responses
tx.send(msg.map(|msg| msg.to_ascii_uppercase())).await;
}
});
Ok(rx.into())
}
#[component]
pub fn App() -> impl IntoView {
use futures::channel::mpsc;
use futures::StreamExt;
let (mut tx, rx) = mpsc::channel(1);
let latest = RwSignal::new(None);
// we'll only listen for websocket messages on the client
if cfg!(feature = "hydrate") {
spawn_local(async move {
match echo_websocket(rx.into()).await {
Ok(mut messages) => {
while let Some(msg) = messages.next().await {
latest.set(Some(msg));
}
}
Err(e) => leptos::logging::warn!("{e}"),
}
});
}
view! {
<input type="text" on:input:target=move |ev| {
tx.try_send(Ok(ev.target().value()));
}/>
<p>{latest}</p>
}
}
What's Changed
- Allow any type that implements FromServerFnError as a replacement of the ServerFnError in server_fn by @ryo33 in #3274
- impl Dispose for Callback types and add try_run to the Callable trait by @basro in #3371
- feat(breaking): allow make
PossibleRouteMatch
dyn-safe by @gbj in #3421 - chore: upgrade
axum
tov0.8
by @sabify in #3439 - feat: Add more options for generating server fn routes by @spencewenski in #3438
- change: allow
IntoFuture
forSuspend::new()
(closes #3509) by @gbj in #3532 - fix: remove
Default
impl forLeptosOptions
andConfFile
by @chrisp60 in #3522 - Fixing closing brace by @thestarmaker in #3539
- AddAnyAttr for AnyView for non-erased by @zakstucke in #3553
- "Update axum paths to 0.8 syntax" by @zakstucke in #3555
- Keep
AddAnyAttr
logic contained by @gbj in #3562 - fix: Actix stream error handling with 0.8 error types by @gbj in #3574
- RenderHtml::into_owned by @zakstucke in #3580
- Binary size wins by @zakstucke in #3566
- Internally erase html elements by @zakstucke in #3614
- feat: support
Option<_>
instyle:
(closes #3568) by @gbj in #3618 - Erased routing, codegen opts by @zakstucke in #3623
- change: remove unused
Result
alias by @gbj in #3543 - feat: support
IntoSplitSignal
for(Signal<T>, SignalSetter<T>)
(closes #3634) by @gbj in #3643 - fix: avoid hydration issues with
HashedStylesheet
(closes #3633) by @gbj in #3654 - Islands router by @gbj in #3502
- Erased mode in CI by @zakstucke in #3640
- fix: tweak bounds on For for backwards-compat by @gbj in #3663
- Implement several into traits for store fields (0.8) by @mahdi739 in #3658
- Implement
IntoClass
for store fields by @mahdi739 in #3670 - fix: Ensure reactive functions passed to
TextProp
are kept reactive (closes: #3689) by @mahdi739 in #3690 - Add websocket support for server functions by @ealmloff in #3656
- fix: broken type inference for
Action::new_unsync
(closes #3328) by @gbj in #3705 - feat(reactive_stores): Replace
AsRef
bound ofStoreFieldIterator
blanket impl withLen
bound by @DanikVitek in #3701 - refactor: make
shell
parameter infile_and_error_handler*
generic by @tversteeg in #3711 - view!{} macro optimisation: don't wrap string types in closures when passing to ToChildren by @zakstucke in #3716
- Remove SendWrapper from the external interface of LocalResource by @zakstucke in #3715
- More flexible server fn macro api by @ealmloff in #3725
- fix(CI): switch to stable in semver for most compatibility by @sabify in #3737
- fix(CI): cancel in-group inflight and pending jobs on new pushes in pull requests by @sabify in #3739
- fix(CI): free-up disk, properly gate nightly feature and pre-install deps by @sabify in #3735
- ArcLocalResource fix (0.8) by @zakstucke in #3741
- ArcLocalResource fix (0.7) by @zakstucke in #3740
- fix(CI): cleanup the directory no matter of the results by @sabify in #3743
- fix(CI): sermver job name by @sabify in #3748
- chore: no need to filter out "nightly" feature as of #3735 by @sabify in #3747
- fix: use signals rather than
Action::new_local()
(closes #3746) by @gbj in #3749 - feat: switch
extract()
helper to useServerFnErrorErr
(closes #3745) by @ilyvion in #3750 - docs(
Effect::watch
): refer todependency_fn
andhandler
args by @jmevel in https://github.com/le...
v0.8.0-rc3
Release notes copied from 0.8.0-alpha/beta/rc1/
. Changelog relative to 0.8.0-rc2
. This release includes some bugfixes that required one additional release.
0.8 has been planned for a while, primarily to accommodate small changes that arose during the course of testing and adopting 0.7, most of which are technically semver-breaking but should not meaningfully affect user code.
If we don't hear any feedback about issues with this rc2
release, we will plan to release it as 0.8.0
in the next week or so.
Noteworthy features:
- Axum 0.8 support. (This alone required a major version bump, as we reexport some Axum types.) (thanks to @sabify for the migration work here)
- Significant improvements to compile times when using
--cfg=erase_components
, which is useful as a dev-mode optimization (thanks to @zakstucke) This is the default setting for debug mode in future releases ofcargo-leptos
, and can be set up manually for use with Trunk. (See docs here.) - Support for the new
islands-router
features that allow a client-side routing experience while using islands (see theislands_router
example) (this one was me) - Improved server function error handling by allowing you to use any type that implements
FromServerFnError
rather than being constrained to useServerFnError
(see #3274). (Note: This will require changes if you're using a custom error type, but should be a better experience.) (thanks to @ryo33) - Support for creating WebSockets via server fns (thanks to @ealmloff)
- Changes to make custom errors significantly more ergonomic when using server functions
LocalResource
no longer exposes aSendWrapper
in the API for the types it returns. (Breaking change: this will require removing some.as_deref()
and so on when usingLocalResource
, but ends up with a much better API.)- Significantly improved DX/bugfixes for thread-local Actions.
As you can see this was a real team effort and, as always, I'm grateful for the contributions of everyone named above, and all those who made commits below.
WebSocket Example
The WebSocket support is particularly exciting, as it allows you to call server functions using the default Rust Stream
trait from the futures
crate, and have those streams send messages over websockets without you needing to know anything about that process. The API landed in a place that feels like a great extension of the "server function" abstraction in which you can make HTTP requests as if they were ordinary async calls. The websocket stuff doesn't integrate directly with Resources/SSR (which make more sense for one-shot things) but is really easy to use:
use server_fn::{codec::JsonEncoding, BoxedStream, ServerFnError, Websocket};
// The websocket protocol can be used on any server function that accepts and returns a [`BoxedStream`]
// with items that can be encoded by the input and output encoding generics.
//
// In this case, the input and output encodings are [`Json`] and [`Json`], respectively which requires
// the items to implement [`Serialize`] and [`Deserialize`].
#[server(protocol = Websocket<JsonEncoding, JsonEncoding>)]
async fn echo_websocket(
input: BoxedStream<String, ServerFnError>,
) -> Result<BoxedStream<String, ServerFnError>, ServerFnError> {
use futures::channel::mpsc;
use futures::{SinkExt, StreamExt};
let mut input = input; // FIXME :-) server fn fields should pass mut through to destructure
// create a channel of outgoing websocket messages
// we'll return rx, so sending a message to tx will send a message to the client via the websocket
let (mut tx, rx) = mpsc::channel(1);
// spawn a task to listen to the input stream of messages coming in over the websocket
tokio::spawn(async move {
while let Some(msg) = input.next().await {
// do some work on each message, and then send our responses
tx.send(msg.map(|msg| msg.to_ascii_uppercase())).await;
}
});
Ok(rx.into())
}
#[component]
pub fn App() -> impl IntoView {
use futures::channel::mpsc;
use futures::StreamExt;
let (mut tx, rx) = mpsc::channel(1);
let latest = RwSignal::new(None);
// we'll only listen for websocket messages on the client
if cfg!(feature = "hydrate") {
spawn_local(async move {
match echo_websocket(rx.into()).await {
Ok(mut messages) => {
while let Some(msg) = messages.next().await {
latest.set(Some(msg));
}
}
Err(e) => leptos::logging::warn!("{e}"),
}
});
}
view! {
<input type="text" on:input:target=move |ev| {
tx.try_send(Ok(ev.target().value()));
}/>
<p>{latest}</p>
}
}
What's Changed
- fix: close Actix websocket stream when browser disconnects (closes #3865) by @gbj in #3866
- Error boundary fixes by @gbj in #3870
- Forward lint attributes used with #[component] macro by @sathish-pv in #3864
- Complete the migration of examples to Tailwind 4 by @nnmm in #3861
- fix: Use stabilized ClipboardEvent by @feathecutie in #3849
- Added header generation method to BrowserResponse by @rakshith-ravi in #3873
- Prevent ScopedFuture stopping owner cleanup by @zakstucke in #3863
- feat: enhancing
ByteStream
error handling by @sabify in #3869 - fix: send/receive websocket data by @sabify in #3848
- feat(examples): add WebSocket example by @sabify in #3853
- chore: put
TextProp
in the prelude (closes #3877) by @huuff in #3879 - fix(examples): websocket example tests fail on latency by @sabify in #3880
- fix: correctly calculate starting index for first new key (closes #3828) by @gbj in #3878
- fix: remove event listeners from Suspense fallback during SSR (closes #3871) by @gbj in #3882
New Contributors
- @sathish-pv made their first contribution in #3864
- @nnmm made their first contribution in #3861
- @feathecutie made their first contribution in #3849
- @huuff made their first contribution in #3879
Full Changelog: v0.8.0-rc2...v0.8.0-rc3
v0.8.0-rc2
Release notes copied from 0.8.0-alpha/beta/rc1
. Changelog relative to 0.8.0-rc1
. This release includes some bugfixes, but is mostly intended to fix compilation on the latest nightly release.
0.8 has been planned for a while, primarily to accommodate small changes that arose during the course of testing and adopting 0.7, most of which are technically semver-breaking but should not meaningfully affect user code.
If we don't hear any feedback about issues with this rc2
release, we will plan to release it as 0.8.0
in the next week or so.
Noteworthy features:
- Axum 0.8 support. (This alone required a major version bump, as we reexport some Axum types.) (thanks to @sabify for the migration work here)
- Significant improvements to compile times when using
--cfg=erase_components
, which is useful as a dev-mode optimization (thanks to @zakstucke) This is the default setting for debug mode in future releases ofcargo-leptos
, and can be set up manually for use with Trunk. (See docs here.) - Support for the new
islands-router
features that allow a client-side routing experience while using islands (see theislands_router
example) (this one was me) - Improved server function error handling by allowing you to use any type that implements
FromServerFnError
rather than being constrained to useServerFnError
(see #3274). (Note: This will require changes if you're using a custom error type, but should be a better experience.) (thanks to @ryo33) - Support for creating WebSockets via server fns (thanks to @ealmloff)
- Changes to make custom errors significantly more ergonomic when using server functions
As you can see this was a real team effort and, as always, I'm grateful for the contributions of everyone named above, and all those who made commits below.
WebSocket Example
The WebSocket support is particularly exciting, as it allows you to call server functions using the default Rust Stream
trait from the futures
crate, and have those streams send messages over websockets without you needing to know anything about that process. The API landed in a place that feels like a great extension of the "server function" abstraction in which you can make HTTP requests as if they were ordinary async calls. The websocket stuff doesn't integrate directly with Resources/SSR (which make more sense for one-shot things) but is really easy to use:
use server_fn::{codec::JsonEncoding, BoxedStream, ServerFnError, Websocket};
// The websocket protocol can be used on any server function that accepts and returns a [`BoxedStream`]
// with items that can be encoded by the input and output encoding generics.
//
// In this case, the input and output encodings are [`Json`] and [`Json`], respectively which requires
// the items to implement [`Serialize`] and [`Deserialize`].
#[server(protocol = Websocket<JsonEncoding, JsonEncoding>)]
async fn echo_websocket(
input: BoxedStream<String, ServerFnError>,
) -> Result<BoxedStream<String, ServerFnError>, ServerFnError> {
use futures::channel::mpsc;
use futures::{SinkExt, StreamExt};
let mut input = input; // FIXME :-) server fn fields should pass mut through to destructure
// create a channel of outgoing websocket messages
// we'll return rx, so sending a message to tx will send a message to the client via the websocket
let (mut tx, rx) = mpsc::channel(1);
// spawn a task to listen to the input stream of messages coming in over the websocket
tokio::spawn(async move {
while let Some(msg) = input.next().await {
// do some work on each message, and then send our responses
tx.send(msg.map(|msg| msg.to_ascii_uppercase())).await;
}
});
Ok(rx.into())
}
#[component]
pub fn App() -> impl IntoView {
use futures::channel::mpsc;
use futures::StreamExt;
let (mut tx, rx) = mpsc::channel(1);
let latest = RwSignal::new(None);
// we'll only listen for websocket messages on the client
if cfg!(feature = "hydrate") {
spawn_local(async move {
match echo_websocket(rx.into()).await {
Ok(mut messages) => {
while let Some(msg) = messages.next().await {
latest.set(Some(msg));
}
}
Err(e) => leptos::logging::warn!("{e}"),
}
});
}
view! {
<input type="text" on:input:target=move |ev| {
tx.try_send(Ok(ev.target().value()));
}/>
<p>{latest}</p>
}
}
What's Changed
- fix: call
additional_context
after providing other server context in all cases by @gbj in #3841 - fix: correctly decode base64-encoded server action error messages stored in URL by @gbj in #3842
- fix: don't try to move keyed elements within the DOM if they're not yet mounted (closes #3844) by @gbj in #3846
- chore(nightly): update proc-macro span file name method name by @gbj in #3852
- fix: reactive_graph keymap impl and clippy warnings by @sabify in #3843
- chore: ran cargo outdated. by @martinfrances107 in #3722
Full Changelog: v0.8.0-rc1...v0.8.0-rc2
0.8.0-rc1
Release notes copied from 0.8.0-alpha/beta
. Changelog relative to 0.8.0-beta
.
0.8 has been planned for a while, primarily to accommodate small changes that arose during the course of testing and adopting 0.7, most of which are technically semver-breaking but should not meaningfully affect user code.
If we don't hear any feedback about issues with this rc1
release, we will plan to release it as 0.8.0
in the next week or so.
Noteworthy features:
- Axum 0.8 support. (This alone required a major version bump, as we reexport some Axum types.) (thanks to @sabify for the migration work here)
- Significant improvements to compile times when using
--cfg=erase_components
, which is useful as a dev-mode optimization (thanks to @zakstucke) This is the default setting for debug mode in future releases ofcargo-leptos
, and can be set up manually for use with Trunk. (See docs here.) - Support for the new
islands-router
features that allow a client-side routing experience while using islands (see theislands_router
example) (this one was me) - Improved server function error handling by allowing you to use any type that implements
FromServerFnError
rather than being constrained to useServerFnError
(see #3274). (Note: This will require changes if you're using a custom error type, but should be a better experience.) (thanks to @ryo33) - Support for creating WebSockets via server fns (thanks to @ealmloff)
- Changes to make custom errors significantly more ergonomic when using server functions
As you can see this was a real team effort and, as always, I'm grateful for the contributions of everyone named above, and all those who made commits below.
WebSocket Example
The WebSocket support is particularly exciting, as it allows you to call server functions using the default Rust Stream
trait from the futures
crate, and have those streams send messages over websockets without you needing to know anything about that process. The API landed in a place that feels like a great extension of the "server function" abstraction in which you can make HTTP requests as if they were ordinary async calls. The websocket stuff doesn't integrate directly with Resources/SSR (which make more sense for one-shot things) but is really easy to use:
use server_fn::{codec::JsonEncoding, BoxedStream, ServerFnError, Websocket};
// The websocket protocol can be used on any server function that accepts and returns a [`BoxedStream`]
// with items that can be encoded by the input and output encoding generics.
//
// In this case, the input and output encodings are [`Json`] and [`Json`], respectively which requires
// the items to implement [`Serialize`] and [`Deserialize`].
#[server(protocol = Websocket<JsonEncoding, JsonEncoding>)]
async fn echo_websocket(
input: BoxedStream<String, ServerFnError>,
) -> Result<BoxedStream<String, ServerFnError>, ServerFnError> {
use futures::channel::mpsc;
use futures::{SinkExt, StreamExt};
let mut input = input; // FIXME :-) server fn fields should pass mut through to destructure
// create a channel of outgoing websocket messages
// we'll return rx, so sending a message to tx will send a message to the client via the websocket
let (mut tx, rx) = mpsc::channel(1);
// spawn a task to listen to the input stream of messages coming in over the websocket
tokio::spawn(async move {
while let Some(msg) = input.next().await {
// do some work on each message, and then send our responses
tx.send(msg.map(|msg| msg.to_ascii_uppercase())).await;
}
});
Ok(rx.into())
}
#[component]
pub fn App() -> impl IntoView {
use futures::channel::mpsc;
use futures::StreamExt;
let (mut tx, rx) = mpsc::channel(1);
let latest = RwSignal::new(None);
// we'll only listen for websocket messages on the client
if cfg!(feature = "hydrate") {
spawn_local(async move {
match echo_websocket(rx.into()).await {
Ok(mut messages) => {
while let Some(msg) = messages.next().await {
latest.set(Some(msg));
}
}
Err(e) => leptos::logging::warn!("{e}"),
}
});
}
view! {
<input type="text" on:input:target=move |ev| {
tx.try_send(Ok(ev.target().value()));
}/>
<p>{latest}</p>
}
}
What's Changed
- Fix typo by @NCura in #3727
- fix: matching optional params after an initial static param (closes #3730) by @gbj in #3732
- docs: update example tailwind input css to v4 by @bimoadityar in #3702
- More flexible server fn macro api by @ealmloff in #3725
- fix(CI): switch to stable in semver for most compatibility by @sabify in #3737
- fix(CI): cancel in-group inflight and pending jobs on new pushes in pull requests by @sabify in #3739
- fix(CI): free-up disk, properly gate nightly feature and pre-install deps by @sabify in #3735
- ArcLocalResource fix (0.8) by @zakstucke in #3741
- ArcLocalResource fix (0.7) by @zakstucke in #3740
- fix(CI): cleanup the directory no matter of the results by @sabify in #3743
- fix(CI): sermver job name by @sabify in #3748
- chore: no need to filter out "nightly" feature as of #3735 by @sabify in #3747
- fix: use signals rather than
Action::new_local()
(closes #3746) by @gbj in #3749 - feat: switch
extract()
helper to useServerFnErrorErr
(closes #3745) by @ilyvion in #3750 - docs(
Effect::watch
): refer todependency_fn
andhandler
args by @jmevel in #3731 - Leptos 0.8 by @gbj in #3529
- chore: ensure WASM target is installed for examples with provided
rust-toolchain.toml
(closes #3717) by @gbj in #3752 - Make trailing comma optional for either macro by @NCura in #3736
- chore: add
SignalSetter
to prelude (closes #3547) by @gbj in #3753 - fix: properly feature gating ui macro tests (Closes #3742) by @sabify in #3756
- fix(CI): optimize CI workflow by @sabify in #3758
- fix(CI): remove duplicate semver ci, #3758 follow-up by @sabify in #3764
- fix(CI): install deps only if needed, speeds up CI by @sabify in #3768
- fix: support
IntoFragment
for single element (closes #3757) by @gbj in #3759 - fix: clippy errors by @sabify in #3772
- fix(CI): install deno only if needed, #3768 follow-up by @sabify in #3773
- fix(CI): remove caching by @sabify in #3776
- fix(CI): conditional executions of only changed examples by @sabify in #3777
- Make docs match reality by @ilyvion in #3775
- fix(CI): toolchain will be determined and test against by CI by @sabify in #3778
- Reduce use local signals for
Action::new_local
and similar primitives by @gbj in #3762 - Tweaks to
MaybeSendWrapperOption<_>
by @gbj in #3781 - fix: correctly handle optional parameters in
ParentRoute
by @gbj in #3784 - fix: router example build process by @sabify in #3779
- fix(CI): run only the exact examples on the only examples change by @sabify in #3782
- Re-export the codee crate by @zakstucke in #3761
- fix: allow repeated
class=
for all tuples, not only static ones (closes #3794) by @gbj in #3801 - Fix Store notification order for nested keyed fields by @gbj in #3799
- Improved handling of
<Title/>
by @gbj in #3793 - derive_local for ArcSignal<T, LocalStorage> by @zakstucke in #3798
- fix: portal example by @sabify in #3785
- feat: add support for more HTTP methods in server fn codecs by @ChosunOne in #3797
- Store test fixes by @gbj in #3803
- Add track_caller to store field methods by @jvdwrf in #3805
- fix: allow custom status codes or redirects for route fallbacks by @gbj in #3808
- fix: Move several Into* trait impls for store fields out of stable module for wider use by @mahdi739 in #3807
- fix: remove
SendOption
from public API of actions by @gbj in https://github.com/leptos-rs/leptos/pul...