Closed Miroito closed 1 year ago
It's not minimum but it gets the point across. It is a slightly modified version of the incremental generation example from the next docs.
Changing the template name to test
(or anything else that is not index
) will work properly.
In 0.3.6, incremental generation on index matched routes like /index/foo
of index/foo/bar
but not /foo
(which is more than acceptable given using incremental generation on the index page is probably bad design in most cases)
use perseus::prelude::*;
use serde::{Deserialize, Serialize};
use sycamore::prelude::*;
#[derive(Serialize, Deserialize, Clone, ReactiveState)]
#[rx(alias = "PageStateRx")]
struct PageState {
title: String,
content: String,
}
#[auto_scope]
fn index_page<G: Html>(cx: Scope, state: &PageStateRx) -> View<G> {
view! { cx,
// Don't worry, there are much better ways of styling in Perseus!
p {
(state.title) (state.content)
}
}
}
#[engine_only_fn]
fn head(cx: Scope) -> View<SsrNode> {
view! { cx,
title { "Welcome to Perseus!" }
}
}
pub fn get_template<G: Html>() -> Template<G> {
Template::build("index")
.build_paths_fn(get_build_paths)
.build_state_fn(get_build_state)
.view_with_state(index_page)
.head(head)
.incremental_generation()
.build()
}
#[engine_only_fn]
async fn get_build_state(
StateGeneratorInfo { path, .. }: StateGeneratorInfo<()>,
) -> Result<PageState, BlamedError<std::io::Error>> {
// This path is illegal, and can't be rendered
// Because we're using incremental generation, we could get literally anything
// as the `path`
let title = path.clone();
let content = format!(
"This is a post entitled '{}'. Its original slug was '{}'.",
&title, &path
);
Ok(PageState { title, content })
}
#[engine_only_fn]
async fn get_build_paths() -> BuildPaths {
BuildPaths {
paths: vec!["".to_string()],
extra: ().into(),
}
}
From some initial testing, it seems like build paths still work perfectly, but incremental generation only works with /
itself, failing in all other cases with a 404. The render configuration is generating /*
as the key for this, which should be correct, as changing it to *
manually fails a number of other pages. This looks like a forward slash stripping mistake somewhere, and I'll need to do some further investigation to figure out exactly what's causing this.
Chances are, this will be in the routing algorithm, since incremental generation is occurring flawlessly for the /
route, and there shouldn't be any other barriers to it.
Okay, this was a simple error on my part: the routing algorithm searches forward by splitting the path into segments over /
, adding /*
to the end of each progressive concatenation to see if there's an incremental match. This would only work for index-level incremental generation, however, if the first element of every path was empty, which is only true for the /
route. Solved by adding an additional case to the end of the algorithm to match all routes when there's incremental generation at the index template (while preserving normal specificity requirements, i.e. more specific routes take precedence).
This will be in beta 21.
This issue is reporting a bug in the code of Perseus. Details of the scope will be available in issue labels. The author described their issue as follows:
The steps to reproduce this issue are as follows:
A minimum reproducible example is available at <>.
Tribble internal data
dHJpYmJsZS1yZXBvcnRlZCxDLWJ1ZyxhdXRob3Itd2lsbGluZy10by1pbXBs