Bot releases are hidden (Show)
Hello everyone, The biggest change in this update is to handle wasm-bindgen 0.2.93 and web_sys 0.3.70 Thanks to @sabify and @maccesch for those PRs. As always, let us know if there's issues.
wasm-bindgen
and web-sys
for leptos 0.6 by @sabify in https://github.com/leptos-rs/leptos/pull/2830
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.13...v0.6.14
Published by gbj 3 months ago
This is a release made from #2607, with updates, bugfixes, and improvements since 0.7.0-alpha.
Most of the release notes for this beta are copied over from the alpha.
0.7 is a nearly-complete rewrite of the internals of the framework, with the following goals:
I am going on vacation for a couple weeks, and my hope is to give some time over the summer for people to really test, explore, and try to migrate.
0.7 works with the current cargo-leptos
version. If you want to start exploring, I've created starter templates for Axum and Actix. Each template is only three files. They show some of the boilerplate differences; for more details, see below.
Axum: cargo leptos new --git https://github.com/leptos-rs/start-axum-0.7
(repo)
Actix: cargo leptos new --git https://github.com/leptos-rs/start-actix-0.7
(repo)
Please use the PR (#2607) or the #07-beta
channel in our Discord for feedback or questions.
Generally speaking, the leptos_0.7
branch will include the latest bug fixes, but any given commit may be broken (sorry!)
.await
on resources and async
in <Suspense/>
Currently, create_resource
allows you to synchronously access the value of some async data as either None
or Some(_)
. However, it requires that you always access it this way. This has some drawbacks:
Now, you can .await
a resource, and you can use async
blocks within a <Suspense/>
via the Suspend
wrapper, which makes it easier to chain two resources:
let user = Resource::new(|| (), |_| user_id());
let posts = Resource::new(
// resources still manually track dependencies (necessary for hydration)
move || user.track(),
move |_| async move {
// but you can .await a resource inside another
let user = user.await?;
get_posts(user).await
},
);
view! {
<Suspense>
// you can `.await` resources to avoid dealing with the `None` state
<p>"User ID: " {move || Suspend::new(async move {
match user.await {
// ...
}
})}</p>
// or you can still use .get() to access resources in things like component props
<For
each=move || posts.get().and_then(Result::ok).unwrap_or_default()
key=|post| post.id
let:post
>
// ...
</For>
</Suspense>
}
One of the awkward edge cases of current Leptos is that our Copy
arena for signals makes it possible to leak memory if you have a collection of nested signals and do not dispose them. (See current example.) 0.7 exposes ArcRwSignal
, ArcReadSignal
, etc., which are Clone
but not Copy
and manage their memory via reference counting, but can easily be converted into the copyable RwSignal
etc. This makes working with nested signal correctly much easier, without sacrificing ergonomics meaningfully. See the 0.7 counters
example for more.
.read()
and .write()
on signalsYou can now use .read()
and .write()
to get immutable and mutable guards for the value of a signal, which will track/update appropriately: these work like .with()
and .update()
but without the extra closure, or like .get()
but without cloning.
let long_vec = RwSignal::new(vec![42; 1000]);
let short_vec = RwSignal::new(vec![13; 2]);
// bad: clones both Vecs
let bad_len = move || long_vec.get().len() + short_vec.get().len();
// ugly: awkward nested syntax (or a macro)
let ugly_len = move || long_vec.with(|long| short_vec.with(|short| long.len() + short.len()));
// readable but doesn't clone
let good_len = move || long_vec.read().len() + short_vec.read().len();
These should always be used for short periods of time, not stored somewhere for longer-term use, just like any guard or lock, or you can cause deadlocks or panics.
The HTML document "shell" for server rendering is currently hardcoded as part of the server integrations, limiting your ability to customize it. Now you simply include it as part of your application, which also means that you can customize things like teh <title>
without needing to use leptos_meta
.
pub fn shell(options: LeptosOptions) -> impl IntoView {
view! {
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<AutoReload options=options.clone() />
<HydrationScripts options/>
<MetaTags/>
</head>
<body>
<App/>
</body>
</html>
}
}
Any valid attribute can now be spread onto any component, allowing you to extend the UI created by a component however you want. This works through multiple components: for example, if you spread attributes onto a Suspense
they will be passed through to whatever it returns.
// attributes that are spread onto a component will be applied to *all* elements returned as part of
// the component's view. to apply attributes to a subset of the component, pass them via a component prop
<ComponentThatTakesSpread
// the class:, style:, prop:, on: syntaxes work just as they do on elements
class:foo=true
style:font-weight="bold"
prop:cool=42
on:click=move |_| alert("clicked ComponentThatTakesSpread")
// props are passed as they usually are on components
some_prop=13
// to pass a plain HTML attribute, prefix it with attr:
attr:id="foo"
// or, if you want to include multiple attributes, rather than prefixing each with
// attr:, you can separate them from component props with the spread {..}
{..} // everything after this is treated as an HTML attribute
title="ooh, a title!"
{..spread_onto_component}
/>
<ProtectedRoute/>
The current ProtectedRoute
component is not great: it checks the condition once, synchronously, on navigation, and so it doesn't respond to changes and can't easily be used with async data. The new ProtectedRoute
is reactive and uses Suspense so you can use resources or reactive data. There are examples of this now in router
and ssr_modes_axum
.
I'm reorganizing the module structure to improve docs and discoverability. We will still have a prelude that can be used for glob imports of almost everything that's currently exported from the root.
- use leptos::*;
+ use leptos::prelude::*;
Likewise, the router exposes things via leptos_router::components
and leptos_router::hooks
. rust-analyzer can help fix imports fairly well.
I'm hoping for feedback on the new module structure, whether it makes sense, and any improvements. I have not done too much work to sort through the reexports, look at how docs look, etc. yet.
We're migrating away from create_
naming toward more idiomatic Rust naming patterns:
create_signal
to signal
(like channel
)create_rw_signal
to RwSignal::new()
I've left some of the current functions in, marked deprecated; others may have been missed, but should be easy to find via docs.rs.
One of the major changes in this release is replacing the View
enum with statically-typed views, which is where most of the binary size savings come from. If you need to branch and return one of several types, you can either use one of the Either
enums in leptos::either
, or you can use .into_any()
to erase the type. Generally speaking the compiler can do its job better if you maintain more type information so the Either
types should be preferred, but AnyView
is not bad to use when needed.
// Either
if some_condition {
Either::Left(view! { <p>"Foo"</p> })
} else {
Either::Right("Bar")
}
// .into_any()
if some_condition {
view! { <p>"Foo"</p> }.into_any()
} else {
"Bar".into_any()
}
There have been changes to the SSR and hydration boilerplate, which include (but aren't limited to)
get_configuration
is sync (remove the .await
).leptos_routes
no longer takes LeptosOptions
as an argumentleptos::mount::hydrate_body
(hydration) instead of leptos::mount::mount_to_body
(which is now CSR-specific)Check the starter templates for a good setup.
The patterns for route definition have changed in several ways.
fallback
is now a required prop on <Routes/>
, rather than an optional prop on <Router/>
<FlatRoutes/>
component that optimizes for this case<ParentRoute/>
path="foo"
becomes path=StaticSegment("foo")
, and there are path=":id"
becomes path=ParamSegment("id")
, path="posts/:id"
becomes path=(StaticSegment("posts"), ParamSegment("id"))
, and so on. There is a path!()
macro that will do this for you: i.e., it will expand path!("/foo/:id")
to path=(StaticSegment("foo"), ParamSegment("id"))
.See the router
and hackernews
examples.
Send
/Sync
signalsBy default, the data held in reactive primitives (signals, memos, effects) must be safe to send across threads. For non-threadsafe types, there is a "storage" generic on signal types. This defaults to SyncStorage
, but you can optionally specify LocalStorage
instead. Many APIs have _local()
alternatives to enable this.
let (foo, bar) = signal("baz");
// error: `std::rc::Rc<&str>` cannot be shared between threads safely
// let (foo, bar) = signal(Rc::new("baz"));
let (foo, bar) = signal_local(Rc::new("baz"));
let qux = RwSignal::new("baz");
// error: `std::rc::Rc<&str>` cannot be shared between threads safely
// let qux = RwSignal::new(Rc::new("baz"));
let qux = RwSignal::new_local(Rc::new("baz"));
I'm sure there are a bunch of small and larger changes I have not mentioned above. By the time of final release, help compiling a total list of breaking changes/migration guide would be much appreciated. At present, the starter templates and the examples
directory in the PR can provide a pretty comprehensive set of changes.
There's a pattern I've seen many use that I do not particularly like, but accidentally enabled through the way APIs happened to be (or needed to be) designed in Leptos 0.1-0.6, in which a user stores some view in a signal and then reads it somewhere else. This was possible because View
needed to be Clone
for internal reasons. Some users used this to create custom control flow: for example, you could create a global "header view" signal, and then update it from leaf components by storing a new view in it.
I'd consider this a bit of an antipattern, for a couple reasons:
Clone
but in a surprising way: you can clone the reference to a DOM node, but that is a shallow, not a deep clone, and if you use it in multiple places by .get()
ing the signal more than once, it will only appear in the last locationIn the statically-typed view tree, views are not necessarily cloneable (including the AnyView
type), so they can't easily be stored in a signal.
However, it is possible to achieve a similar goal by using a "reactive channel" pattern instead:
let count = RwSignal::new(0);
let trigger = ArcTrigger::new();
let (tx, rx) = std::sync::mpsc::channel();
let on_click = {
let trigger = trigger.clone();
move |_| {
leptos::logging::log!("clicked");
*count.write() += 1;
tx.send(if *count.read() % 2 == 0 {
view! { <p>"An even paragraph"</p> }.into_any()
} else {
view! { <span>"An odd span"</span> }.into_any()
})
.unwrap();
trigger.trigger();
}
};
view! {
<div>
<button on:click=on_click>"Update view"</button>
{move || {
trigger.track();
rx.try_recv().unwrap_or_else(|_| view! {
<p>"Click the button once to begin."</p>
}.into_any())
}}
</div>
}
Send the views through a channel means they do not need to be cloned, and won't be used in more than once place (avoiding the edge cases of 2 above.) Each time you send a view through the channel, simply trigger the trigger.
Published by gbj 3 months ago
This release mostly includes a series of small bugfixes (see below), but also includes a fix for the annoying issues we'd been having with rust-analyzer (#2527).
rkyv
feature interaction with Axum integration by @gbj in https://github.com/leptos-rs/leptos/pull/2631
ToChildren
by @spencewenski in https://github.com/leptos-rs/leptos/pull/2643
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.12...v0.6.13
Published by gbj 4 months ago
This is a release made from #2607, now that the 0.7 branch has reached a relatively stable state, and all of the examples are in working condition.
0.7 is a nearly-complete rewrite of the internals of the framework, with the following goals:
My goal between now and the end of July is to fill in the remaining missing pieces and release a beta version.
0.7 works with the current cargo-leptos
version. If you want to start exploring, I've created starter templates for Axum and Actix. Each template is only three files. They show some of the boilerplate differences; for more details, see below.
Axum: cargo leptos new --git https://github.com/leptos-rs/start-axum-0.7
(repo)
Actix: cargo leptos new --git https://github.com/leptos-rs/start-actix-0.7
(repo)
Please use the PR (#2607) or the #preview
channel in our Discord for feedback or questions.
Generally speaking, the leptos_0.7
branch will include the latest bug fixes, but any given commit may be broken (sorry!)
.await
on resources and async
in <Suspense/>
Currently, create_resource
allows you to synchronously access the value of some async data as either None
or Some(_)
. However, it requires that you always access it this way. This has some drawbacks:
Now, you can .await
a resource, and you can use async
blocks within a <Suspense/>
via the Suspend
wrapper, which makes it easier to chain two resources:
let user = Resource::new(|| (), |_| user_id());
let posts = Resource::new(
// resources still manually track dependencies (necessary for hydration)
move || user.track(),
move |_| async move {
// but you can .await a resource inside another
let user = user.await?;
get_posts(user).await
},
);
view! {
<Suspense>
// you can `.await` resources to avoid dealing with the `None` state
<p>"User ID: " {move || Suspend(async move {
match user.await {
// ...
}
})}</p>
// or you can still use .get() to access resources in things like component props
<For
each=move || posts.get().and_then(Result::ok).unwrap_or_default()
key=|post| post.id
let:post
>
// ...
</For>
</Suspense>
}
One of the awkward edge cases of current Leptos is that our Copy
arena for signals makes it possible to leak memory if you have a collection of nested signals and do not dispose them. (See current example.) 0.7 exposes ArcRwSignal
, ArcReadSignal
, etc., which are Clone
but not Copy
and manage their memory via reference counting, but can easily be converted into the copyable RwSignal
etc. This makes working with nested signal correctly much easier, without sacrificing ergonomics meaningfully. See the 0.7 counters
example for more.
.read()
and .write()
on signalsYou can now use .read()
and .write()
to get immutable and mutable guards for the value of a signal, which will track/update appropriately: these work like .with()
and .update()
but without the extra closure, or like .get()
but without cloning.
let long_vec = RwSignal::new(vec![42; 1000]);
let short_vec = RwSignal::new(vec![13; 2]);
// bad: clones both Vecs
let bad_len = move || long_vec.get().len() + short_vec.get().len();
// ugly: awkward nested syntax (or a macro)
let ugly_len = move || long_vec.with(|long| short_vec.with(|short| long.len() + short.len()));
// readable but doesn't clone
let good_len = move || long_vec.read().len() + short_vec.read().len();
These should always be used for short periods of time, not stored somewhere for longer-term use, just like any guard or lock, or you can cause deadlocks or panics.
The HTML document "shell" for server rendering is currently hardcoded as part of the server integrations, limiting your ability to customize it. Now you simply include it as part of your application, which also means that you can customize things like teh <title>
without needing to use leptos_meta
.
pub fn shell(options: LeptosOptions) -> impl IntoView {
view! {
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<AutoReload options=options.clone() />
<HydrationScripts options/>
<MetaTags/>
</head>
<body>
<App/>
</body>
</html>
}
}
Any valid attribute can now be spread onto any component, allowing you to extend the UI created by a component however you want. This works through multiple components: for example, if you spread attributes onto a Suspense
they will be passed through to whatever it returns.
// attributes that are spread onto a component will be applied to *all* elements returned as part of
// the component's view. to apply attributes to a subset of the component, pass them via a component prop
<ComponentThatTakesSpread
// the class:, style:, prop:, on: syntaxes work just as they do on elements
class:foo=true
style:font-weight="bold"
prop:cool=42
on:click=move |_| alert("clicked ComponentThatTakesSpread")
// props are passed as they usually are on components
some_prop=13
// to pass a plain HTML attribute, prefix it with attr:
attr:id="foo"
// or, if you want to include multiple attributes, rather than prefixing each with
// attr:, you can separate them from component props with the spread {..}
{..} // everything after this is treated as an HTML attribute
title="ooh, a title!"
{..spread_onto_component}
/>
<ProtectedRoute/>
The current ProtectedRoute
component is not great: it checks the condition once, synchronously, on navigation, and so it doesn't respond to changes and can't easily be used with async data. The new ProtectedRoute
is reactive and uses Suspense so you can use resources or reactive data. There are examples of this now in router
and ssr_modes_axum
.
<ProtectedRoute/>
Suspend(_)
without a <Suspense/>
set_is_routing
<Body/>
etc. instead of Vec<AnyAttribute>
IntoView
on an arbitrary structLazy
routes and hydration (what do you do while hydrating if the code for the route hasn't been lazy-loaded yet?)path!()
macro to make route definitions easier in routerCopy
but !Send
for !Send
data (like browser things)I'm reorganizing the module structure to improve docs and discoverability. We will still have a prelude that can be used for glob imports of almost everything that's currently exported from the root.
- use leptos::*;
+ use leptos::prelude::*;
Likewise, the router exposes things via leptos_router::components
and leptos_router::hooks
. rust-analyzer can help fix imports fairly well.
I'm hoping for feedback on the new module structure, whether it makes sense, and any improvements. I have not done too much work to sort through the reexports, look at how docs look, etc. yet.
We're migrating away from create_
naming toward more idiomatic Rust naming patterns:
create_signal
to signal
(like channel
)create_rw_signal
to RwSignal::new()
I've left some of the current functions in, marked deprecated; others may have been missed, but should be easy to find via docs.rs.
One of the major changes in this release is replacing the View
enum with statically-typed views, which is where most of the binary size savings come from. If you need to branch and return one of several types, you can either use one of the Either
enums in leptos::either
, or you can use .into_any()
to erase the type. Generally speaking the compiler can do its job better if you maintain more type information so the Either
types should be preferred, but AnyView
is not bad to use when needed.
// Either
if some_condition {
Either::Left(view! { <p>"Foo"</p> })
} else {
Either::Right("Bar")
}
// .into_any()
if some_condition {
view! { <p>"Foo"</p> }.into_any()
} else {
"Bar".into_any()
}
There have been changes to the SSR and hydration boilerplate, which include (but aren't limited to)
get_configuration
is sync (remove the .await
).leptos_routes
no longer takes LeptosOptions
as an argumentleptos::mount::hydrate_body
(hydration) instead of leptos::mount::mount_to_body
(which is now CSR-specific)Check the starter templates for a good setup.
The patterns for route definition have changed in several ways.
fallback
is now a required prop on <Routes/>
, rather than an optional prop on <Router/>
<FlatRoutes/>
component that optimizes for this case<ParentRoute/>
path="foo"
becomes path=StaticSegment("foo")
, and there are path=":id"
becomes path=ParamSegment("id")
, path="posts/:id"
becomes path=(StaticSegment("posts"), ParamSegment("id"))
, and so on. I plan to create a path!()
macro that will do this for you, and just haven't done it yet.See the router
and hackernews
examples.
Send
/Sync
signalsThe data held in reactive primitives (signals, memos, effects) must be safe to send across threads. Threading the needle of the type system in order to ensure thread safety on the server while allowing flexibility in the browser (where you generally don't have multiple threads and where most types are !Send
) is complicated. If you have browser-only types that need to be stored in signals, you can use the send_wrapper
crate to wrap them. We also have _unsync
versions of several APIs that allow you to use !Send
types: see example.
I'm sure there are a bunch of small and larger changes I have not mentioned above. By the time of final release, help compiling a total list of breaking changes/migration guide would be much appreciated. At present, the starter templates and the examples
directory in the PR can provide a pretty comprehensive set of changes.
There's a pattern I've seen many use that I do not particularly like, but accidentally enabled through the way APIs happened to be (or needed to be) designed in Leptos 0.1-0.6, in which a user stores some view in a signal and then reads it somewhere else. This was possible because View
needed to be Clone
for internal reasons. Some users used this to create custom control flow: for example, you could create a global "header view" signal, and then update it from leaf components by storing a new view in it.
I'd consider this a bit of an antipattern, for a couple reasons:
Clone
but in a surprising way: you can clone the reference to a DOM node, but that is a shallow, not a deep clone, and if you use it in multiple places by .get()
ing the signal more than once, it will only appear in the last locationIn the statically-typed view tree, views are not necessarily cloneable (including the AnyView
type), so they can't easily be stored in a signal.
However, it is possible to achieve a similar goal by using a "reactive channel" pattern instead:
let count = RwSignal::new(0);
let trigger = ArcTrigger::new();
let (tx, rx) = std::sync::mpsc::channel();
let on_click = {
let trigger = trigger.clone();
move |_| {
leptos::logging::log!("clicked");
*count.write() += 1;
tx.send(if *count.read() % 2 == 0 {
view! { <p>"An even paragraph"</p> }.into_any()
} else {
view! { <span>"An odd span"</span> }.into_any()
})
.unwrap();
trigger.trigger();
}
};
view! {
<div>
<button on:click=on_click>"Update view"</button>
{move || {
trigger.track();
rx.try_recv().unwrap_or_else(|_| view! {
<p>"Click the button once to begin."</p>
}.into_any())
}}
</div>
}
Send the views through a channel means they do not need to be cloned, and won't be used in more than once place (avoiding the edge cases of 2 above.) Each time you send a view through the channel, simply trigger the trigger.
Published by gbj 5 months ago
This is mainly a maintenance release, but includes a couple new features that I want to point out:
impl Trait
in Component PropsYou can now use impl Trait
syntax directly in component props, rather than explicitly specifying a generic and a where
clause
#[component]
fn ProgressBar<F>(#[prop(default = 100)] max: u16, progress: F) -> impl IntoView
where
F: Fn() -> i32 + 'static,
{
view! {
<progress
max=max
value=progress
/>
}
}
#[component]
fn ProgressBar(
#[prop(default = 100)] max: u16,
progress: impl Fn() -> i32 + 'static,
) -> impl IntoView {
view! {
<progress
max=max
value=progress
/>
}
}
In the following code Bar
doesn't currently inherit attributes from Foo
when it spreads its attributes. PR #2534 fixes this.
fn main() {
let (count, set_count) = create_signal(0);
mount_to_body(move || {
view! {
<Foo
attr:hello=move || count.get().to_string()
/>
<button on:click=move|_| { set_count.update(|count| *count += 1) }>"+ count"</button>
}
});
}
#[component]
fn Foo(#[prop(attrs)] attrs: Vec<(&'static str, Attribute)>) -> impl IntoView {
view! {
<Bar {..attrs} />
}
}
#[component]
fn Bar(#[prop(attrs)] attrs: Vec<(&'static str, Attribute)>) -> impl IntoView {
view! {
<div {..attrs}>"hello world"</div>
}
}
<ActionForm>
on formmethod="dialog"
submission (closes #2523) by @gbj in https://github.com/leptos-rs/leptos/pull/2531
Oco
separately as oco_ref
crate so that it can be used elsewhere by @gbj in https://github.com/leptos-rs/leptos/pull/2536
input_derive
parameter to #[server]
macro (closes #2544) by @luxalpa in https://github.com/leptos-rs/leptos/pull/2545
empty_docs
warnings in #[component]
macro by @abusch in https://github.com/leptos-rs/leptos/pull/2574
--release
) by @gbj in https://github.com/leptos-rs/leptos/pull/2587
#[component]
now handles impl Trait
by converting to generic type params, fix #2274 by @MingweiSamuel in https://github.com/leptos-rs/leptos/pull/2599
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.11...v0.6.12
Published by gbj 6 months ago
The -preview
here is intended to convey: Here is a mostly-working but pre-alpha release of what I've been working on for the last six months or so. This work can be found in the leptos-0.7
branch. Enough work has been done that many (but not all) of the examples in the repo are functioning. This release is a fairly complete rewrite of the internals of the entire framework. You should expect both missing APIs and bugs.
Note the following:
0.7.0-preview2
to the Cargo.toml
of an existing app and expect it to workuse leptos::*;
to use leptos::prelude::*;
and then using modules and reexports more sanely from the main crate0.7.0-preview
playground that includes the setup of a basic app with comments. You should be able to expand from there.The following examples in the repo are known to work and can be useful to learn from
counter
counters
error_boundary
fetch
todomvc
parent_child
router
todo_app_sqlite_axum
ssr_modes_axum
Cargo.toml
setupuse leptos::prelude::*
instead of use leptos::*
Send
/Sync
. In general for values being stored in signals this means you need to use Arc
on occasion instead of Rc
, etc.
send_wrapper
crate. Better ergonomics here are an open questionIntoView
trait work quite differently from before. In general, for type-erased views (.into_view()
previously) you can use .into_any()
or the Either::
types. Storing a View
in a signal, cloning it, etc. are not viable approaches any more: store data in signals and rendering views, rather than storing views in signals.Arc
equivalents to each signal type (ArcRwSignal
, ArcMemo
, etc.) which manage their lifecycle via reference counting rather than the reactive ownership graph. This can be used for things like iterating over nested signals (see counters
example) and pushing signals "up" in the tree, rather than using the manual .dispose()
and owner manipulation patternsRwSignal::new()
, signal()
instead of create_signal()
to match channel()
, etc.)path!()
macro to parse the old strings into this format but it's not implemented.on:
on components (e82227aa07023855ac704c4f484a466109c3f8cc)MaybeSignal
Signal::with()
cargo-leptos
hot reloading-alpha
!Send/!Sync
thread-local arena for browser-type signalsTry things out, see what breaks, see what feels good. How can we improve the module imports? What are pain points? etc. Feel free to comment here or on Discord in the #preview
channel,
Published by gbj 6 months ago
The primary purpose of this release is that it includes a fix for an unfortunate memory leak when using leptos_router
on the server.
Also included are
spread
example for the full set of possibilities)IntoView
directly for Rc<str>
view
macroIt's important to me to say that all three of the new features above were implemented by community members. This release brings us to over 250 total contributors over time, not to mention everyone who's done work on docs, templates, or libraries that exist outside this repo. Thank you to everyone who's been involved in this project so far.
Location
header when using leptos_actix::redirect()
without JS/WASM (closes #2506) by @gbj in https://github.com/leptos-rs/leptos/pull/2507
counter_isomorphic
by @gbj in https://github.com/leptos-rs/leptos/pull/2510
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.10...v0.6.11
Published by gbj 7 months ago
Mostly a patch release with a number of bugfixes, as well as some nice quality-of-life improvements:
#[prop(attrs)]
on slotson:
to dynamic children of components (i.e., when you do <MyComponent on:.../>
, the event listener is now applied correctly to more of the children of <MyComponent/>
)view! {}
in hot-reloading code (closes #2421) by @gbj in https://github.com/leptos-rs/leptos/pull/2478
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.9...v0.6.10
Published by benwis 8 months ago
Mostly this release exists to fix imports in Cargo, as well as a few minor bug fixes
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.8...v0.6.9
Published by benwis 8 months ago
Mostly this release is to disable file hashing by default, and streamline it's use. It can now be enabled by setting hash-files=true
in your Cargo.toml or setting the LEPTOS_HASH_FILES=true
env var when running cargo-leptos. If you're using Docker or moving the bin to a new folder, you need to copy the (by default) hash.txt
file from target/{release_profile_name}
to the same folder as your binary, and make sure the env var or cargo.toml option is enabled. Also some minor bug fixes
PartialEq
removed from create_owning_memo
by @zroug in https://github.com/leptos-rs/leptos/pull/2394
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.7...v0.6.8
Published by benwis 8 months ago
Hello everyone! Some lovely changes in here. My favorite is the addition of version hashes to css,js, and wasm files to automatically invalidate browser caching issues. Be sure to update to the latest version of cargo leptos(v0.2.8) to test out this feature. As always, big thanks to our returning contributors and welcome to the new folks!
impl_from
argument to #[server]
proc_macro by @videobitva in https://github.com/leptos-rs/leptos/pull/2335
FromUtf8Error
in oco.rs
by @zoomiti in https://github.com/leptos-rs/leptos/pull/2318
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.6...v0.6.7
Published by benwis 8 months ago
Fixed some issues with examples, integrated a server macro for Spin, and improved a number of typos. Thanks to all that participated!
For general 0.6 release notes, see here.
cargo fmt
by @martinfrances107 in https://github.com/leptos-rs/leptos/pull/2254
.into()
calls consistent by @blorbb in https://github.com/leptos-rs/leptos/pull/2249
.dispatch()
an action immediately (closes #2225) by @gbj in https://github.com/leptos-rs/leptos/pull/2286
server_fn
by @gbj in https://github.com/leptos-rs/leptos/pull/2320
tailwind_axum
by @gbj in https://github.com/leptos-rs/leptos/pull/2324
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.5...v0.6.6
Published by gbj 9 months ago
This fixes a few bugs that have popped up since 0.6. For general 0.6 release notes, see here.
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.4...v0.6.5
Published by gbj 9 months ago
This fixes a few bugs that have popped up since 0.6.3. For general 0.6 migration notes, see here.
edtion = "2021"
in rustfmt.toml
by @chrisp60 in https://github.com/leptos-rs/leptos/pull/2235
create_local_resource
(closes #2237) by @gbj in https://github.com/leptos-rs/leptos/pull/2238
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.3...v0.6.4
Published by gbj 9 months ago
This is release for our new server functions rewrite and Axum 0.7 support.
This should be a relatively feature-rich release, with limited breaking changes.
.handle_server_fns()
call in your main.rs
, as server functions are now handled in .leptos_routes()
extract
function has been removed, and replaced with a new extract
that has the same API as the current extractor
. I think this API is strictly better, but please share feedback if you disagree.http
1.0 and tower_http
0.5.).handle_server_fns()
call in your main.rs
, as server functions are now handled in .leptos_routes()
extract
function has been removed, and replaced with a new extract
that has the same API as the current extractor
. I think this API is strictly better, but please share feedback if you disagree.RequestParts
has been removed, as http::request::Parts
now implements Clone
: any use_context::<RequestParts>()
should be updated to use Parts
directly instead.ServerFnError::new()
The addition of custom error types means that constructing ServerFnError
inside server functions can cause type inference errors:
let oops = Err(ServerFnError::ServerError("No server state".to_string()));
return oops; // this is fine
oops? // this is not: cannot infer type of the type parameter `E` declared on the enum `ServerFnError`
As a result, we've added a helper ServerFnError::new
which simply constructs a ServerFnError::<NoCustomError>::ServerError
:
let oops = Err(ServerFnError::new("No server state"));
return oops; // this is fine
oops? // this is also fine now
This has the benefit of being more concise than the earlier pattern in any case.
A rewritten server function system that is backwards-compatible, but reduces binary size and increases flexibility, specifically by allowing
.leptos_routes()
from the integrationsIntoReq
, FromReq
, IntoRes
, and/or FromRes
traits#[middleware]
macro to add per-server-function middleware from the Tower or Actix ecosystems (#1461)Note: The additional included encodings (serde_lite
, rkyv
, multipart form data) are all enabled by additive features on the server_fn
crate. If you want to use them you can just add that crate as a dependency and enable the required features.
Example: You can find a comprehensive example of these new features in the new server_fns_axum
example.
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.5.7...0.6.3
Published by gbj 9 months ago
This is release for our new server functions rewrite and Axum 0.7 support.
This should be a relatively feature-rich release, with limited breaking changes.
.handle_server_fns()
call in your main.rs
, as server functions are now handled in .leptos_routes()
extract
function has been removed, and replaced with a new extract
that has the same API as the current extractor
. I think this API is strictly better, but please share feedback if you disagree.http
1.0 and tower_http
0.5.).handle_server_fns()
call in your main.rs
, as server functions are now handled in .leptos_routes()
extract
function has been removed, and replaced with a new extract
that has the same API as the current extractor
. I think this API is strictly better, but please share feedback if you disagree.RequestParts
has been removed, as http::request::Parts
now implements Clone
: any use_context::<RequestParts>()
should be updated to use Parts
directly instead.ServerFnError::new()
The addition of custom error types means that constructing ServerFnError
inside server functions can cause type inference errors:
let oops = Err(ServerFnError::ServerError("No server state".to_string()));
return oops; // this is fine
oops? // this is not: cannot infer type of the type parameter `E` declared on the enum `ServerFnError`
As a result, we've added a helper ServerFnError::new
which simply constructs a ServerFnError::<NoCustomError>::ServerError
:
let oops = Err(ServerFnError::new("No server state"));
return oops; // this is fine
oops? // this is also fine now
This has the benefit of being more concise than the earlier pattern in any case.
A rewritten server function system that is backwards-compatible, but reduces binary size and increases flexibility, specifically by allowing
.leptos_routes()
from the integrationsIntoReq
, FromReq
, IntoRes
, and/or FromRes
traits#[middleware]
macro to add per-server-function middleware from the Tower or Actix ecosystems (#1461)Note: The additional included encodings (serde_lite
, rkyv
, multipart form data) are all enabled by additive features on the server_fn
crate. If you want to use them you can just add that crate as a dependency and enable the required features.
Example: You can find a comprehensive example of these new features in the new server_fns_axum
example.
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.5.7...0.6.2
Published by benwis 9 months ago
This is release for our new server functions rewrite and Axum 0.7 support.
This should be a relatively feature-rich release, with limited breaking changes.
.handle_server_fns()
call in your main.rs
, as server functions are now handled in .leptos_routes()
extract
function has been removed, and replaced with a new extract
that has the same API as the current extractor
. I think this API is strictly better, but please share feedback if you disagree..handle_server_fns()
call in your main.rs
, as server functions are now handled in .leptos_routes()
extract
function has been removed, and replaced with a new extract
that has the same API as the current extractor
. I think this API is strictly better, but please share feedback if you disagree.RequestParts
has been removed, as http::request::Parts
now implements Clone
: any use_context::<RequestParts>()
should be updated to use Parts
directly instead.ServerFnError::new()
The addition of custom error types means that constructing ServerFnError
inside server functions can cause type inference errors:
let oops = Err(ServerFnError::ServerError("No server state".to_string()));
return oops; // this is fine
oops? // this is not: cannot infer type of the type parameter `E` declared on the enum `ServerFnError`
As a result, we've added a helper ServerFnError::new
which simply constructs a ServerFnError::<NoCustomError>::ServerError
:
let oops = Err(ServerFnError::new("No server state"));
return oops; // this is fine
oops? // this is also fine now
This has the benefit of being more concise than the earlier pattern in any case.
A rewritten server function system that is backwards-compatible, but reduces binary size and increases flexibility, specifically by allowing
.leptos_routes()
from the integrationsIntoReq
, FromReq
, IntoRes
, and/or FromRes
traits#[middleware]
macro to add per-server-function middleware from the Tower or Actix ecosystems (#1461)Note: The additional included encodings (serde_lite
, rkyv
, multipart form data) are all enabled by additive features on the server_fn
crate. If you want to use them you can just add that crate as a dependency and enable the required features.
Example: You can find a comprehensive example of these new features in the new server_fns_axum
example.
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.5.6...v0.6.1
Published by gbj 9 months ago
This is prerelease for our new server functions rewrite and Axum 0.7 support.
This should be a relatively feature-rich release, with limited breaking changes.
I'm interested in gathering feedback in the discussion associated with this release.
.handle_server_fns()
call in your main.rs
, as server functions are now handled in .leptos_routes()
extract
function has been removed, and replaced with a new extract
that has the same API as the current extractor
. I think this API is strictly better, but please share feedback if you disagree..handle_server_fns()
call in your main.rs
, as server functions are now handled in .leptos_routes()
extract
function has been removed, and replaced with a new extract
that has the same API as the current extractor
. I think this API is strictly better, but please share feedback if you disagree.RequestParts
has been removed, as http::request::Parts
now implements Clone
: any use_context::<RequestParts>()
should be updated to use Parts
directly instead.A rewritten server function system that is backwards-compatible, but reduces binary size and increases flexibility, specifically by allowing
.leptos_routes()
from the integrationsIntoReq
, FromReq
, IntoRes
, and/or FromRes
traits#[middleware]
macro to add per-server-function middleware from the Tower or Actix ecosystems (#1461)Note: The additional included encodings (serde_lite
, rkyv
, multipart form data) are all enabled by additive features on the server_fn
crate. If you want to use them you can just add that crate as a dependency and enable the required features.
Example: You can find a comprehensive example of these new features in the new server_fns_axum
example.
trailing_slash
support by @gbj in https://github.com/leptos-rs/leptos/pull/2203
axum-session
because old version was yanked by @gbj in https://github.com/leptos-rs/leptos/pull/2205
View::render_to_string
panic by @chrisp60 in https://github.com/leptos-rs/leptos/pull/2200
leptos_meta
should not enable tracing
feature on leptos
by default (closes #2158) by @gbj in https://github.com/leptos-rs/leptos/pull/2211
Default
for LeptosOptions
, ConfFile
by @chrisp60 in https://github.com/leptos-rs/leptos/pull/2208
leptos_axum
's default feature (#1846) by @gbj in https://github.com/leptos-rs/leptos/pull/2213
#[server]
macro by @gbj in https://github.com/leptos-rs/leptos/pull/2216
.refetch()
should not include any tracked reads by @gbj in https://github.com/leptos-rs/leptos/pull/2222
Full Changelog: https://github.com/leptos-rs/leptos/compare/v0.6.0-beta...0.6.0-rc1
Published by gbj 9 months ago
This has been a rocky week for releases. While finalizing the work on 0.6.0, I intended to publish a final 0.5.5 that would contain all the remaining changes to the 0.5 series. Unfortunately, this release contained two serious issues:
trailing_slash
changes to the router in 0.5.5 broke the current routing behavior in several situations (see #2203 for details)Because some (many?) existing 0.5 apps would break with this new feature under 0.5 — and worse, because they would compile and then either panic or display the wrong page — I decide to revert the feature immediately. This meant a semver-breaking change between 0.5.6 and 0.5.7, so I have yanked 0.5.5 and 0.5.6 of all the crates.
We've added some appropriate regression tests for those issues. Apologies to anyone whose work was affected by this!
Published by gbj 9 months ago
This is a beta release for our new server functions rewrite and Axum 0.7 support.
This should be a relatively feature-rich release, with limited breaking changes.
I'm interested in gathering feedback in the discussion associated with this release.
.handle_server_fns()
call in your main.rs
, as server functions are now handled in .leptos_routes()
extract
function has been removed, and replaced with a new extract
that has the same API as the current extractor
. I think this API is strictly better, but please share feedback if you disagree..handle_server_fns()
call in your main.rs
, as server functions are now handled in .leptos_routes()
extract
function has been removed, and replaced with a new extract
that has the same API as the current extractor
. I think this API is strictly better, but please share feedback if you disagree.A rewritten server function system that is backwards-compatible, but reduces binary size and increases flexibility, specifically by allowing
.leptos_routes()
from the integrationsIntoReq
, FromReq
, IntoRes
, and/or FromRes
traits#[middleware]
macro to add per-server-function middleware from the Tower or Actix ecosystems (#1461)Note: The additional included encodings (serde_lite
, rkyv
, multipart form data) are all enabled by additive features on the server_fn
crate. If you want to use them you can just add that crate as a dependency and enable the required features.
Example: You can find a comprehensive example of these new features in the new server_fns_axum
example.