Skip to content

Commit

Permalink
refactor: ♻️ removed useless render options system
Browse files Browse the repository at this point in the history
  • Loading branch information
arctic-hen7 committed Jul 31, 2021
1 parent ac79996 commit 1af26dc
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 101 deletions.
9 changes: 7 additions & 2 deletions examples/showcase/server/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use actix_web::{web, App, HttpRequest, HttpServer, Result as ActixResult, error};
use actix_files::{NamedFile};
use sycamore::prelude::SsrNode;
use std::collections::HashMap;

use perseus::{
serve::{get_render_cfg, get_page},
render_cfg::RenderCfg,
config_manager::FsConfigManager,
template::TemplateMap
};
Expand Down Expand Up @@ -48,7 +48,12 @@ async fn js_bundle() -> std::io::Result<NamedFile> {
async fn wasm_bundle() -> std::io::Result<NamedFile> {
NamedFile::open("../app/pkg/perseus_showcase_app_bg.wasm")
}
async fn page_data(req: HttpRequest, templates: web::Data<TemplateMap<SsrNode>>, render_cfg: web::Data<RenderCfg>, config_manager: web::Data<FsConfigManager>) -> ActixResult<String> {
async fn page_data(
req: HttpRequest,
templates: web::Data<TemplateMap<SsrNode>>,
render_cfg: web::Data<HashMap<String, String>>,
config_manager: web::Data<FsConfigManager>
) -> ActixResult<String> {
let path = req.match_info().query("filename");
// TODO match different types of errors here
let page_data = get_page(path, &render_cfg, &templates, config_manager.get_ref()).map_err(error::ErrorNotFound)?;
Expand Down
52 changes: 11 additions & 41 deletions src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
use crate::{
template::Template,
config_manager::ConfigManager,
render_cfg::{RenderOpt, RenderCfg, TemplatesCfg, PagesCfg}
};
use crate::errors::*;
use std::collections::HashMap;
Expand All @@ -18,56 +17,36 @@ pub fn build_template(
config_manager: &impl ConfigManager
) -> Result<
(
Vec<RenderOpt>,
Vec<String>,
bool
)
> {
let mut render_opts: Vec<RenderOpt> = Vec::new();
let mut single_page = false;
let template_path = template.get_path();

// Handle the boolean properties
if template.revalidates() {
render_opts.push(RenderOpt::Revalidated);
}
if template.uses_incremental() {
render_opts.push(RenderOpt::Incremental);
}

// Handle static path generation
// Because we iterate over the paths, we need a base path if we're not generating custom ones (that'll be overriden if needed)
let paths = match template.uses_build_paths() {
true => {
render_opts.push(RenderOpt::StaticPaths);
template.get_build_paths()?
},
true => template.get_build_paths()?,
false => {
single_page = true;
vec![String::new()]
}
};
// Add the rest of the render options before we loop over defined pages
if template.uses_build_state() {
render_opts.push(RenderOpt::StaticProps);
}
if template.uses_request_state() {
render_opts.push(RenderOpt::Server);
}

// Iterate through the paths to generate initial states if needed
for path in paths.iter() {
// If needed, we'll contruct a full path that's URL encoded so we can easily save it as a file
// BUG: insanely nested paths won't work whatsoever if the filename is too long, maybe hash instead?
let full_path = match render_opts.contains(&RenderOpt::StaticPaths) {
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()
};

// Handle static initial state generation
// We'll only write a static state if one is explicitly generated
if render_opts.contains(&RenderOpt::StaticProps) {
if template.uses_build_state() {
// We pass in the latter part of the path, without the base specifier (because that would be the same for everything in the template)
let initial_state = template.get_build_state(path.to_string())?;
// Write that intial state to a static JSON file
Expand All @@ -89,7 +68,6 @@ pub fn build_template(
// If the template is very basic, prerender without any state
// It's safe to add a property to the render options here because `.is_basic()` will only return true if path generation is not being used (or anything else)
if template.is_basic() {
render_opts.push(RenderOpt::StaticProps);
let prerendered = sycamore::render_to_string(
||
template.render_for_template(None)
Expand All @@ -100,55 +78,47 @@ pub fn build_template(
}
}

Ok((render_opts, paths, single_page))
Ok((paths, single_page))
}

// TODO function to build pages
/// Runs the build process of building many different templates.
pub fn build_templates(templates: Vec<Template<SsrNode>>, config_manager: &impl ConfigManager) -> Result<()> {
let mut templates_conf: TemplatesCfg = HashMap::new();
let mut pages_conf: PagesCfg = HashMap::new();
// The render configuration stores a list of pages to the root paths of their templates
let mut render_cfg = HashMap::new();
// Create each of the templates
for template in templates {
let template_root_path = template.get_path();
let is_incremental = template.uses_incremental();

let (render_opts, pages, single_page) = build_template(template, config_manager)?;
templates_conf.insert(
template_root_path.clone(),
render_opts
);
let (pages, single_page) = build_template(template, config_manager)?;
// If the tempalte represents a single page itself, we don't need any concatenation
if single_page {
pages_conf.insert(
render_cfg.insert(
template_root_path.clone(),
template_root_path.clone()
);
} else {
// Add each page that the template explicitly generated (ignoring ISR for now)
for page in pages {
pages_conf.insert(
render_cfg.insert(
format!("{}/{}", &template_root_path, &page),
template_root_path.clone()
);
}
// Now if the page uses ISR, add an explicit `/*` in there after the template root path
// Incremental rendering requires build-time path generation
if is_incremental {
pages_conf.insert(
render_cfg.insert(
format!("{}/*", &template_root_path),
template_root_path.clone()
);
}
}
}

let render_conf = RenderCfg {
templates: templates_conf,
pages: pages_conf
};
config_manager
.write("./dist/render_conf.json", &serde_json::to_string(&render_conf)?)?;
.write("./dist/render_conf.json", &serde_json::to_string(&render_cfg)?)?;

Ok(())
}
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
pub mod errors;
pub mod shell;
pub mod serve;
pub mod render_cfg;
pub mod config_manager;
pub mod template;
pub mod build;
38 changes: 0 additions & 38 deletions src/render_cfg.rs

This file was deleted.

31 changes: 12 additions & 19 deletions src/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
use std::fs;
use serde::{Serialize, Deserialize};
use crate::errors::*;
use crate::render_cfg::{RenderCfg, RenderOpt};
use crate::config_manager::ConfigManager;
use crate::template::TemplateMap;
use sycamore::prelude::SsrNode;
use std::collections::HashMap;

/// Represents the data necessary to render a page.
#[derive(Serialize, Deserialize, Debug, Clone)]
Expand All @@ -19,9 +19,9 @@ pub struct PageData {
}

/// Gets the configuration of how to render each page.
pub fn get_render_cfg() -> Result<RenderCfg> {
pub fn get_render_cfg() -> Result<HashMap<String, String>> {
let content = fs::read_to_string("../app/dist/render_conf.json")?;
let cfg = serde_json::from_str::<RenderCfg>(&content)?;
let cfg = serde_json::from_str::<HashMap<String, String>>(&content)?;

Ok(cfg)
}
Expand All @@ -30,7 +30,7 @@ pub fn get_render_cfg() -> Result<RenderCfg> {
// TODO let this function take a request struct of some form
pub fn get_page(
path: &str,
render_cfg: &RenderCfg,
render_cfg: &HashMap<String, String>,
templates: &TemplateMap<SsrNode>,
config_manager: &impl ConfigManager
) -> Result<PageData> {
Expand All @@ -40,7 +40,7 @@ pub fn get_page(
// Match the path to one of the templates
let mut template_name = String::new();
// We'll try a direct match first
if let Some(template_root_path) = render_cfg.pages.get(path) {
if let Some(template_root_path) = render_cfg.get(path) {
template_name = template_root_path.to_string();
}
// Next, an ISR match (more complex)
Expand All @@ -56,7 +56,7 @@ pub fn get_page(
} + "/*";

// If we find something, keep going until we don't (maximise specificity)
if let Some(template_root_path) = render_cfg.pages.get(&path_to_try) {
if let Some(template_root_path) = render_cfg.get(&path_to_try) {
template_name = template_root_path.to_string();
} else {
break;
Expand All @@ -66,33 +66,26 @@ pub fn get_page(
bail!(ErrorKind::PageNotFound(path.to_string()))
}

// Get the render options of the template
let render_opts = render_cfg.templates.get(&template_name);
let render_opts = match render_opts {
Some(render_opts) => render_opts,
// Get the template to use
let template = templates.get(&template_name);
let template = match template {
Some(template) => template,
None => bail!(ErrorKind::PageNotFound(path.to_string()))
};

let html: String;
let state: Option<String>;

// TODO remove render options system altogether now that we're passing pages around
// Handle each different type of rendering (static paths have already been done though, so we don't need to deal with them)
if render_opts.contains(&RenderOpt::StaticProps) {
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
state = match config_manager.read(&format!("../app/dist/static/{}.json", path_encoded)) {
Ok(state) => Some(state),
Err(_) => None
};
} else if render_opts.contains(&RenderOpt::Server) {
// Get the template itself (we need it for generation)
let template = templates.get(&template_name);
let template = match template {
Some(template) => template,
None => bail!(ErrorKind::PageNotFound(path.to_string()))
};
} else if template.uses_request_state() {
// Generate the initial state (this may generate an error, but there's no file that can't exist)
state = Some(template.get_request_state(path.to_string())?);
// Use that to render the static HTML
Expand Down

0 comments on commit 1af26dc

Please sign in to comment.