From f5e398c933c7f998687580c570d0d5feca325de4 Mon Sep 17 00:00:00 2001 From: aleidk Date: Mon, 21 Apr 2025 20:14:07 -0400 Subject: [PATCH] wip: change assets handling to vite-rs --- frontend/templates/base.html | 4 +-- src/router.rs | 19 ++++------ src/static_assets.rs | 48 ++++++++++++++++++++----- src/static_assets/template_functions.rs | 16 +++++++++ vite.config.ts | 3 ++ 5 files changed, 66 insertions(+), 24 deletions(-) create mode 100644 src/static_assets/template_functions.rs diff --git a/frontend/templates/base.html b/frontend/templates/base.html index 72ee0b1..908c0eb 100644 --- a/frontend/templates/base.html +++ b/frontend/templates/base.html @@ -5,8 +5,8 @@ - - + {{ load_vite_script() | safe }} + diff --git a/src/router.rs b/src/router.rs index 3b3a990..ae96ef9 100644 --- a/src/router.rs +++ b/src/router.rs @@ -1,8 +1,8 @@ use axum::http::StatusCode; use axum::{ extract::{Path, State}, - http::{header, HeaderMap, HeaderValue}, - response::Html, + http::{header, HeaderMap, HeaderValue} + , routing::get, Router, }; @@ -25,8 +25,7 @@ async fn handle_assets( State(state): State<AppState>, Path(asset_path): Path<String>, ) -> Result<(HeaderMap, String)> { - let full_path = format!("frontend/assets/{}", asset_path); - let asset: ViteFile = state.assets.get_asset(&full_path).ok_or(Error::HTTP(StatusCode::NOT_FOUND))?; + let asset: ViteFile = state.assets.get_asset(&asset_path).ok_or(Error::HTTP(StatusCode::NOT_FOUND))?; let mut headers = HeaderMap::new(); headers.insert(header::CONTENT_TYPE, HeaderValue::from_str(&asset.content_type).unwrap()); @@ -47,21 +46,15 @@ async fn handler_home( HxRequest(hx_request): HxRequest, mut tx: Tx, ) -> ResultTemplate { - let template = state.assets.get_template("index.html").ok_or(Error::HTTP(StatusCode::NOT_FOUND))?; - let rows = sqlx::query_as::<_, ExampleRow>("select 'Postgres' as database, setting as version, current_database(), current_user, current_timestamp from pg_settings where name = 'server_version'") .fetch_all(&mut tx) .await?; - println!("{:?}", rows); - let content = if hx_request { - template - .eval_to_state(context!(rows => rows))? - .render_block("htmx")? + state.assets.render_template_block("index.html", "htmx", context!(rows => rows))? } else { - template.render(context!(rows => rows))? + state.assets.render_template("index.html", context!(rows => rows))? }; - Ok(Html(content)) + Ok(content) } diff --git a/src/static_assets.rs b/src/static_assets.rs index 48e5718..77cbf78 100644 --- a/src/static_assets.rs +++ b/src/static_assets.rs @@ -1,9 +1,16 @@ -use minijinja::{path_loader, Environment, Template}; +mod template_functions; + +use crate::static_assets::template_functions::load_functions; +use crate::ResultTemplate; +use axum::response::Html; +use minijinja::{path_loader, Environment}; use minijinja_autoreload::AutoReloader; +use serde::Serialize; use vite_rs::{ViteFile, ViteProcess}; #[derive(vite_rs::Embed)] #[root = "."] +#[dev_server_port = "3001"] struct Static; pub struct Assets { @@ -24,18 +31,20 @@ impl Clone for Assets { impl Assets { pub fn new() -> Self { - #[allow(unused_mut)] let mut templates = Environment::new(); + let mut templates = Environment::new(); + load_functions(&mut templates); + templates.set_loader(minijinja::path_loader("frontend/templates")); let mut _guard = None; let mut _reloader = None; // Load in dev mode #[cfg(debug_assertions)] { - // templates.set_loader(minijinja::path_loader("frontend/templates")); _guard = Static::start_dev_server(true); _reloader = Some(AutoReloader::new(|notifier| { - let template_path = "path/to/templates"; + let template_path = "frontend/templates"; let mut env = Environment::new(); + load_functions(&mut env); env.set_loader(path_loader(template_path)); notifier.watch_path(template_path, true); Ok(env) @@ -61,15 +70,36 @@ impl Assets { Static::get(full_path.as_str()) } - pub fn get_template(&self, path: &str) -> Option<Template> { - match &self._reloader { + pub fn render_template<S: Serialize>(&self, path: &str, ctx: S) -> ResultTemplate { + let env = match &self._reloader { None => { - self.templates.get_template(path).ok() + &self.templates } Some(reloader) => { - reloader.acquire_env().unwrap().get_template(path).ok() + &reloader.acquire_env()? } - } + }; + + let result = env.get_template(path)?.render(ctx)?; + + Ok(Html(result)) + } + + pub fn render_template_block<S: Serialize>(&self, path: &str, block: &str, ctx: S) -> ResultTemplate { + let env = match &self._reloader { + None => { + &self.templates + } + Some(reloader) => { + &reloader.acquire_env()? + } + }; + + let result = env.get_template(path)? + .eval_to_state(ctx)? + .render_block(block)?; + + Ok(Html(result)) } } diff --git a/src/static_assets/template_functions.rs b/src/static_assets/template_functions.rs new file mode 100644 index 0000000..3c8f3a9 --- /dev/null +++ b/src/static_assets/template_functions.rs @@ -0,0 +1,16 @@ +use minijinja::Environment; + +fn load_vite_script() -> &'static str { + #[cfg(debug_assertions)] + { + r#"<script src="http://localhost:3001/@vite/client" type="module"></script>"# + } + + #[cfg(not(debug_assertions))] + { + "" + } +} +pub(super) fn load_functions(env: &mut Environment) { + env.add_function("load_vite_script", load_vite_script); +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index 6c6a600..1653759 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,6 +2,9 @@ import {defineConfig} from "vite"; export default defineConfig({ plugins: [], + server: { + port: 3001, + }, build: { rollupOptions: { input: [