mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-27 09:54:41 -05:00
preload lazy routes without creating data twice
This commit is contained in:
@@ -32,7 +32,7 @@ where
|
||||
}
|
||||
|
||||
async fn preload(&self) {
|
||||
T::data().view().await;
|
||||
T::preload().await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ pub trait LazyRoute: Send + 'static {
|
||||
fn data() -> Self;
|
||||
|
||||
fn view(self) -> impl Future<Output = AnyView>;
|
||||
|
||||
fn preload() -> impl Future<Output = ()> {
|
||||
async {}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -8,9 +8,7 @@ use proc_macro::{TokenStream, TokenTree};
|
||||
use proc_macro2::Span;
|
||||
use proc_macro_error2::{abort, proc_macro_error};
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{
|
||||
spanned::Spanned, Block, Ident, ImplItem, ItemImpl, Path, Type, TypePath,
|
||||
};
|
||||
use syn::{spanned::Spanned, Ident, ImplItem, ItemImpl, Path, Type, TypePath};
|
||||
|
||||
const RFC3986_UNRESERVED: [char; 4] = ['-', '.', '_', '~'];
|
||||
const RFC3986_PCHAR_OTHER: [char; 1] = ['@'];
|
||||
@@ -233,6 +231,28 @@ fn lazy_route_impl(
|
||||
_ => abort!(self_ty.span(), "only path types are supported"),
|
||||
};
|
||||
let lazy_view_ident = Ident::new(&ty_name_to_snake, im.self_ty.span());
|
||||
let preload_lazy_view_ident = Ident::new(
|
||||
&format!("__preload_{lazy_view_ident}"),
|
||||
lazy_view_ident.span(),
|
||||
);
|
||||
|
||||
im.items.push(
|
||||
syn::parse::<ImplItem>(
|
||||
quote! {
|
||||
async fn preload() {
|
||||
// TODO for 0.9 this is not precise
|
||||
// we don't split routes for wasm32 ssr
|
||||
// but we don't require a `hydrate`/`csr` feature on leptos_router
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#preload_lazy_view_ident().await;
|
||||
}
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.unwrap_or_else(|e| {
|
||||
abort!(e.span(), "could not parse preload item impl")
|
||||
}),
|
||||
);
|
||||
|
||||
let item = im.items.iter_mut().find_map(|item| match item {
|
||||
ImplItem::Fn(inner) => {
|
||||
@@ -244,28 +264,31 @@ fn lazy_route_impl(
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
match item {
|
||||
None => abort!(im.span(), "must contain a fn called `view`"),
|
||||
Some(fun) => {
|
||||
let body = fun.block.clone();
|
||||
let new_block = quote! {{
|
||||
#[::leptos::lazy(#lazy_view_ident)]
|
||||
async fn view(this: #self_ty) -> ::leptos::prelude::AnyView {
|
||||
#body
|
||||
let body = std::mem::replace(
|
||||
&mut fun.block,
|
||||
syn::parse(
|
||||
quote! {
|
||||
{
|
||||
#lazy_view_ident(self).await
|
||||
}
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
view(self).await
|
||||
}};
|
||||
let block =
|
||||
syn::parse::<Block>(new_block.into()).unwrap_or_else(|e| {
|
||||
abort!(
|
||||
e.span(),
|
||||
"`lazy_route` can only be used on an `impl` block"
|
||||
)
|
||||
});
|
||||
fun.block = block;
|
||||
return quote! {
|
||||
#[::leptos::lazy]
|
||||
async fn #lazy_view_ident(this: #self_ty) -> ::leptos::prelude::AnyView {
|
||||
#body
|
||||
}
|
||||
|
||||
#im
|
||||
}.into();
|
||||
}
|
||||
}
|
||||
|
||||
quote! { #im }.into()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user