From fb6757484da5cf7e0951db2c01d96ec3e5059cc9 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 2 May 2023 11:05:21 -0500 Subject: [PATCH] pull out serve static assets methods --- .../examples/axum-router/src/main.rs | 8 +-- packages/fullstack/server-macro/src/lib.rs | 3 +- .../fullstack/src/adapters/axum_adapter.rs | 71 ++++++++++++++----- .../fullstack/src/adapters/salvo_adapter.rs | 48 ++++++++++--- 4 files changed, 94 insertions(+), 36 deletions(-) diff --git a/packages/fullstack/examples/axum-router/src/main.rs b/packages/fullstack/examples/axum-router/src/main.rs index 83c0fac58..96567c791 100644 --- a/packages/fullstack/examples/axum-router/src/main.rs +++ b/packages/fullstack/examples/axum-router/src/main.rs @@ -40,20 +40,16 @@ fn main() { .unwrap() .block_on(async move { let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 8080)); - use tower_http::services::ServeDir; - - // Serve the dist/assets folder with the javascript and WASM files created by the CLI - let serve_dir = ServeDir::new("dist/assets"); axum::Server::bind(&addr) .serve( axum::Router::new() + // Serve the dist/assets folder with the javascript and WASM files created by the CLI + .serve_static_assets("./dist") // Register server functions .register_server_fns("") // Connect to the hot reload server .connect_hot_reload() - // Serve the static assets folder - .nest_service("/assets", serve_dir) // If the path is unknown, render the application .fallback( move |uri: http::uri::Uri, State(ssr_state): State| { diff --git a/packages/fullstack/server-macro/src/lib.rs b/packages/fullstack/server-macro/src/lib.rs index bdf755289..f6df526c1 100644 --- a/packages/fullstack/server-macro/src/lib.rs +++ b/packages/fullstack/server-macro/src/lib.rs @@ -15,8 +15,7 @@ use server_fn_macro::*; /// (e.g., `"/api"`). Defaults to `"/"`. /// 3. *Optional*: either `"Cbor"` (specifying that it should use the binary `cbor` format for /// serialization), `"Url"` (specifying that it should be use a URL-encoded form-data string). -/// Defaults to `"Url"`. If you want to use this server function to power a `
` that will -/// work without WebAssembly, the encoding must be `"Url"`. If you want to use this server function +/// Defaults to `"Url"`. If you want to use this server function /// using Get instead of Post methods, the encoding must be `"GetCbor"` or `"GetJson"`. /// /// The server function itself can take any number of arguments, each of which should be serializable diff --git a/packages/fullstack/src/adapters/axum_adapter.rs b/packages/fullstack/src/adapters/axum_adapter.rs index 6da33c1df..32ce190cd 100644 --- a/packages/fullstack/src/adapters/axum_adapter.rs +++ b/packages/fullstack/src/adapters/axum_adapter.rs @@ -125,6 +125,7 @@ pub trait DioxusRouterExt { /// axum::Server::bind(&addr) /// .serve( /// axum::Router::new() + /// // Register server functions routes with the default handler /// .register_server_fns("") /// .into_make_service(), /// ) @@ -148,7 +149,7 @@ pub trait DioxusRouterExt { /// axum::Server::bind(&addr) /// .serve( /// axum::Router::new() - /// // Server side render the application, serve static assets, and register server functions + /// // Connect to hot reloading in debug mode /// .connect_hot_reload() /// .into_make_service(), /// ) @@ -158,6 +159,36 @@ pub trait DioxusRouterExt { /// ``` fn connect_hot_reload(self) -> Self; + /// Serves the static WASM for your Dioxus application (except the generated index.html). + /// + /// # Example + /// ```rust + /// #![allow(non_snake_case)] + /// use dioxus::prelude::*; + /// use dioxus_fullstack::prelude::*; + /// + /// #[tokio::main] + /// async fn main() { + /// let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 8080)); + /// axum::Server::bind(&addr) + /// .serve( + /// axum::Router::new() + /// // Server side render the application, serve static assets, and register server functions + /// .serve_static_assets(ServeConfigBuilder::new(app, ())) + /// // Server render the application + /// // ... + /// .into_make_service(), + /// ) + /// .await + /// .unwrap(); + /// } + /// + /// fn app(cx: Scope) -> Element { + /// todo!() + /// } + /// ``` + fn serve_static_assets(self, assets_path: impl Into) -> Self; + /// Serves the Dioxus application. This will serve a complete server side rendered application. /// This will serve static assets, server render the application, register server functions, and intigrate with hot reloading. /// @@ -233,20 +264,16 @@ where }) } - fn serve_dioxus_application( - mut self, - server_fn_route: &'static str, - cfg: impl Into>, - ) -> Self { + fn serve_static_assets(mut self, assets_path: impl Into) -> Self { use tower_http::services::{ServeDir, ServeFile}; - let cfg = cfg.into(); + let assets_path = assets_path.into(); // Serve all files in dist folder except index.html - let dir = std::fs::read_dir(cfg.assets_path).unwrap_or_else(|e| { + let dir = std::fs::read_dir(&assets_path).unwrap_or_else(|e| { panic!( "Couldn't read assets directory at {:?}: {}", - &cfg.assets_path, e + &assets_path, e ) }); @@ -256,7 +283,7 @@ where continue; } let route = path - .strip_prefix(cfg.assets_path) + .strip_prefix(&assets_path) .unwrap() .iter() .map(|segment| { @@ -267,7 +294,6 @@ where .collect::>() .join("/"); let route = format!("/{}", route); - println!("Serving static asset at {}", route); if path.is_dir() { self = self.nest_service(&route, ServeDir::new(path)); } else { @@ -275,13 +301,24 @@ where } } + self + } + + fn serve_dioxus_application( + mut self, + server_fn_route: &'static str, + cfg: impl Into>, + ) -> Self { + let cfg = cfg.into(); + // Add server functions and render index.html - self.route( - "/", - get(render_handler).with_state((cfg, SSRState::default())), - ) - .connect_hot_reload() - .register_server_fns(server_fn_route) + self.serve_static_assets(&cfg.assets_path) + .route( + "/", + get(render_handler).with_state((cfg, SSRState::default())), + ) + .connect_hot_reload() + .register_server_fns(server_fn_route) } fn connect_hot_reload(self) -> Self { diff --git a/packages/fullstack/src/adapters/salvo_adapter.rs b/packages/fullstack/src/adapters/salvo_adapter.rs index 9468ec0fe..2c5ef0b1f 100644 --- a/packages/fullstack/src/adapters/salvo_adapter.rs +++ b/packages/fullstack/src/adapters/salvo_adapter.rs @@ -153,6 +153,25 @@ pub trait DioxusRouterExt { /// } fn connect_hot_reload(self) -> Self; + /// Serves the static WASM for your Dioxus application (except the generated index.html). + /// + /// # Example + /// ```rust + /// use salvo::prelude::*; + /// use std::{net::TcpListener, sync::Arc}; + /// use dioxus_fullstack::prelude::*; + /// + /// #[tokio::main] + /// async fn main() { + /// let router = Router::new() + /// .server_static_assets("/dist"); + /// Server::new(TcpListener::bind("127.0.0.1:8080")) + /// .serve(router) + /// .await; + /// } + /// ``` + fn serve_static_assets(self, assets_path: impl Into) -> Self; + /// Serves the Dioxus application. This will serve a complete server side rendered application. /// This will serve static assets, server render the application, register server functions, and intigrate with hot reloading. /// @@ -213,18 +232,14 @@ impl DioxusRouterExt for Router { }) } - fn serve_dioxus_application( - mut self, - server_fn_route: &'static str, - cfg: impl Into>, - ) -> Self { - let cfg = cfg.into(); + fn serve_static_assets(mut self, assets_path: impl Into) -> Self { + let assets_path = assets_path.into(); // Serve all files in dist folder except index.html - let dir = std::fs::read_dir(cfg.assets_path).unwrap_or_else(|e| { + let dir = std::fs::read_dir(&assets_path).unwrap_or_else(|e| { panic!( "Couldn't read assets directory at {:?}: {}", - &cfg.assets_path, e + &assets_path, e ) }); @@ -234,7 +249,7 @@ impl DioxusRouterExt for Router { continue; } let route = path - .strip_prefix(&cfg.assets_path) + .strip_prefix(&assets_path) .unwrap() .iter() .map(|segment| { @@ -255,8 +270,19 @@ impl DioxusRouterExt for Router { } } - self.connect_hot_reload() - .register_server_fns(server_fn_route) + self + } + + fn serve_dioxus_application( + self, + server_fn_path: &'static str, + cfg: impl Into>, + ) -> Self { + let cfg = cfg.into(); + + self.serve_static_assets(&cfg.assets_path) + .connect_hot_reload() + .register_server_fns(server_fn_path) .push(Router::with_path("/").get(SSRHandler { cfg })) }