Skip to content

Commit

Permalink
feat: ✨ added isr
Browse files Browse the repository at this point in the history
  • Loading branch information
arctic-hen7 committed Aug 1, 2021
1 parent 1af26dc commit 5baf9bf
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 20 deletions.
1 change: 1 addition & 0 deletions examples/showcase/app/src/bin/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ fn main() {
pages::index::get_page::<SsrNode>(),
pages::about::get_page::<SsrNode>(),
pages::post::get_page::<SsrNode>(),
pages::new_post::get_page::<SsrNode>(),
pages::ip::get_page::<SsrNode>()
], &config_manager).expect("Static generation failed!");

Expand Down
6 changes: 6 additions & 0 deletions examples/showcase/app/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ enum AppRoute {
Index,
#[to("/about")]
About,
#[to("/post/new")]
NewPost,
#[to("/post/<slug>")]
Post {
slug: String
Expand Down Expand Up @@ -52,6 +54,10 @@ pub fn run() -> Result<(), JsValue> {
format!("post/{}", slug),
pages::post::template_fn()
),
AppRoute::NewPost => app_shell(
"post/new".to_string(),
pages::new_post::template_fn()
),
AppRoute::Ip => app_shell(
"ip".to_string(),
pages::ip::template_fn()
Expand Down
2 changes: 2 additions & 0 deletions examples/showcase/app/src/pages/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod index;
pub mod about;
pub mod post;
pub mod ip;
pub mod new_post;

use perseus::{get_templates_map, template::Template};
use sycamore::prelude::GenericNode;
Expand All @@ -13,6 +14,7 @@ pub fn get_templates_map<G: GenericNode>() -> HashMap<String, Template<G>> {
index::get_page::<G>(),
about::get_page::<G>(),
post::get_page::<G>(),
new_post::get_page::<G>(),
ip::get_page::<G>()
]
}
21 changes: 21 additions & 0 deletions examples/showcase/app/src/pages/new_post.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use sycamore::prelude::{template, component, GenericNode, Template as SycamoreTemplate};
use perseus::template::Template;

#[component(NewPostPage<G>)]
pub fn new_post_page() -> SycamoreTemplate<G> {
template! {
p { "New post creator." }
}
}

pub fn get_page<G: GenericNode>() -> Template<G> {
Template::new("post/new")
.template(template_fn())
}

pub fn template_fn<G: GenericNode>() -> perseus::template::TemplateFn<G> {
Box::new(|_| template! {
NewPostPage()
}
)
}
2 changes: 1 addition & 1 deletion examples/showcase/app/src/pages/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub fn get_page<G: GenericNode>() -> Template<G> {

pub fn get_static_props(path: String) -> String {
let path_vec: Vec<&str> = path.split('/').collect();
let title_slug = path_vec[0];
let title_slug = path_vec[path_vec.len() - 1];
// This is just an example
let title = urlencoding::decode(title_slug).unwrap();
let content = format!("This is a post entitled '{}'. Its original slug was '{}'.", title, title_slug);
Expand Down
2 changes: 1 addition & 1 deletion examples/showcase/bonnie.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ build.cmd = [
"wasm-pack build --target web",
"rollup ./main.js --format iife --file ./pkg/bundle.js"
]
build.subcommands.--watch = "find ../../ -not -path \"../../target/*\" -not -path \"../../.git/*\" | entr -s \"bonnie build\""
build.subcommands.--watch = "find ../../ -not -path \"../../target/*\" -not -path \"../../.git/*\" -not -path \"../../examples/showcase/app/dist/*\" | entr -s \"bonnie build\""
serve = [
"cd server",
"cargo watch -w ../../../ -x \"run\""
Expand Down
2 changes: 1 addition & 1 deletion src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub fn build_template(
let full_path = match template.uses_build_paths() {
true => urlencoding::encode(&format!("{}/{}", &template_path, path)).to_string(),
// We don't want to concatenate the name twice if we don't have to
false => template_path.clone()
false => urlencoding::encode(&template_path).to_string()
};

// Handle static initial state generation
Expand Down
64 changes: 47 additions & 17 deletions src/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,25 @@ pub fn get_page(
if let Some(template_root_path) = render_cfg.get(path) {
template_name = template_root_path.to_string();
}
// Next, an ISR match (more complex)
// We progressively look for more and more specificity of the path, adding each segment
// That way, we're searching forwards rather than backwards, which is more efficient
let path_segments: Vec<&str> = path.split('/').collect();
for (idx, _) in path_segments.iter().enumerate() {
// Make a path out of this and all the previous segments
// For some reason, [0..0] gives nothing, so we need to `match` here
let path_to_try = match idx {
0 => path_segments[0].to_string(),
_ => path_segments[0..idx].join("/")
} + "/*";
// Next, an ISR match (more complex), which we only want to run if we didn't get an exact match above
if template_name.is_empty() {
// We progressively look for more and more specificity of the path, adding each segment
// That way, we're searching forwards rather than backwards, which is more efficient
let path_segments: Vec<&str> = path.split('/').collect();
for (idx, _) in path_segments.iter().enumerate() {
// Make a path out of this and all the previous segments
let path_to_try = path_segments[0..(idx + 1)].join("/") + "/*";

// If we find something, keep going until we don't (maximise specificity)
if let Some(template_root_path) = render_cfg.get(&path_to_try) {
template_name = template_root_path.to_string();
} else {
break;
// If we find something, keep going until we don't (maximise specificity)
if let Some(template_root_path) = render_cfg.get(&path_to_try) {
template_name = template_root_path.to_string();
} else {
break;
}
}
}

// if we still have nothing, then the page doesn't exist
if template_name.is_empty() {
bail!(ErrorKind::PageNotFound(path.to_string()))
}
Expand All @@ -77,7 +77,37 @@ pub fn get_page(
let state: Option<String>;

// Handle each different type of rendering (static paths have already been done though, so we don't need to deal with them)
if template.uses_build_state() || template.is_basic() {
// TODO make this system completely modular with state amalgamation
if template.uses_incremental() {
// The template uses ISR, check if it's already been rendered before and cached
let html_res = config_manager.read(&format!("../app/dist/static/{}.html", path_encoded));
if matches!(html_res, Ok(_)) && !cfg!(debug_assertions) {
html = html_res.unwrap();
// Get the static JSON (if it exists, but it should)
state = match config_manager.read(&format!("../app/dist/static/{}.json", path_encoded)) {
Ok(state) => Some(state),
Err(_) => None
};
} else {
// Note that we assume ISR is used with SSG (otherwise it would be completely pointless...)
// We need to generate and cache this page for future usage
state = Some(
template.get_build_state(
format!("{}/{}", template.get_path(), path)
)?
);
html = sycamore::render_to_string(
||
template.render_for_template(state.clone())
);
// Cache all that
config_manager
.write(&format!("../app/dist/static/{}.json", path_encoded), &state.clone().unwrap())?;
// Write that prerendered HTML to a static file
config_manager
.write(&format!("../app/dist/static/{}.html", path_encoded), &html)?;
}
} else if template.uses_build_state() || template.is_basic() {
// Get the static HTML
html = config_manager.read(&format!("../app/dist/static/{}.html", path_encoded))?;
// Get the static JSON
Expand Down
1 change: 1 addition & 0 deletions src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub struct Template<G: GenericNode>
/// A length of time after which to prerender the template again. This is equivalent to ISR in NextJS.
revalidate_after: Option<String>,
}
// TODO mandate usage conditions (e.g. ISR needs SSG)
impl<G: GenericNode> Template<G> {
/// Creates a new template definition.
pub fn new(path: impl Into<String> + std::fmt::Display) -> Self {
Expand Down

0 comments on commit 5baf9bf

Please sign in to comment.