Simplify the launch builder (#2967)

* improve documentation for the fullstack server context

* Add a section about axum integration to the crate root docs

* make serve_dioxus_application accept the cfg builder directly

* remove unused server_fn module

* improve fullstack config docs

* improve documentation for the server function macro

* fix axum router extension link

* Fix doc tests

* Fix launch builder

* Simplify the launch builder

* don't re-export launch in the prelude

* refactor fullstack launch

* Fix fullstack launch builder

* Update static generation with the new builder api

* fix some formatting/overly broad launch replacements

* fix custom menu example

* fix fullstack/static generation examples

* Fix static generation launch

* A few small formatting fixes

* Fix a few doc tests

* implement LaunchConfig for serve configs

* fix fullstack launch with separate web and server launch methods

* fix check with all features

* dont expose inner core module

* clippy and check

* fix readme

---------

Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
Evan AlmloffandJonathan Kelley authored and GitHub committed 2024-10-10 16:00:58 -07:00
1 parent 2d7bef44e8
commit 20d146d9bd
126 files changed
+618 -989

No files matched your search

+4 -16
View File
@@ -2,6 +2,8 @@
use std::path::PathBuf;
use dioxus_lib::prelude::dioxus_core::LaunchConfig;
/// Settings for a statically generated site that may be hydrated in the browser
pub struct Config {
#[cfg(feature = "server")]
@@ -25,12 +27,10 @@ pub struct Config {
#[cfg(feature = "server")]
pub(crate) github_pages: bool,
#[cfg(feature = "web")]
#[allow(unused)]
pub(crate) web_cfg: dioxus_web::Config,
}
impl LaunchConfig for Config {}
#[allow(clippy::derivable_impls)]
impl Default for Config {
fn default() -> Self {
@@ -49,8 +49,6 @@ impl Default for Config {
additional_routes: vec!["/".to_string()],
#[cfg(feature = "server")]
github_pages: false,
#[cfg(feature = "web")]
web_cfg: dioxus_web::Config::default(),
}
}
}
@@ -144,16 +142,6 @@ impl Config {
}
myself
}
/// Set the web config.
///
/// This method will only effect the hydrated web renderer.
#[cfg(feature = "web")]
#[cfg_attr(docsrs, doc(cfg(feature = "web")))]
pub fn web_cfg(self, web_cfg: dioxus_web::Config) -> Self {
#[allow(clippy::needless_update)]
Self { web_cfg, ..self }
}
}
#[cfg(feature = "server")]
+7 -58
View File
@@ -2,25 +2,15 @@
use std::any::Any;
use dioxus_lib::prelude::{Element, VirtualDom};
pub use crate::Config;
use dioxus_lib::prelude::Element;
/// Launch a fullstack app with the given root component, contexts, and config.
#[allow(unused)]
pub fn launch(
root: fn() -> Element,
contexts: Vec<Box<dyn Fn() -> Box<dyn Any + Send + Sync> + Send + Sync>>,
platform_config: Config,
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
platform_config: Vec<Box<dyn Any>>,
) {
let virtual_dom_factory = move || {
let mut vdom = VirtualDom::new(root);
for context in &contexts {
vdom.insert_any_root_context(context());
}
vdom
};
#[cfg(feature = "server")]
tokio::runtime::Runtime::new()
.unwrap()
@@ -33,56 +23,15 @@ pub fn launch(
use http::StatusCode;
use tower_http::services::ServeDir;
use tower_http::services::ServeFile;
let platform_config = platform_config
.into_iter()
.find_map(|cfg| cfg.downcast::<crate::Config>().map(|cfg| *cfg).ok())
.unwrap_or_else(crate::Config::new);
let github_pages = platform_config.github_pages;
let path = platform_config.output_dir.clone();
crate::ssg::generate_static_site(root, platform_config)
.await
.unwrap();
// Serve the program if we are running with cargo
if std::env::var_os("CARGO").is_some() || dioxus_cli_config::is_cli_enabled() {
// Get the address the server should run on. If the CLI is running, the CLI proxies static generation into the main address
// and we use the generated address the CLI gives us
let serve_address = dioxus_cli_config::fullstack_address_or_localhost();
// Point the user to the CLI address if the CLI is running or the fullstack address if not
println!(
"Serving static files from {} at http://{serve_address}",
path.display()
);
let mut serve_dir =
ServeDir::new(path.clone()).call_fallback_on_method_not_allowed(true);
let mut router = axum::Router::new();
// If we are acting like github pages, we need to serve the 404 page if the user requests a directory that doesn't exist
router = if github_pages {
router.fallback_service(
serve_dir.fallback(ServeFile::new(path.join("404/index.html"))),
)
} else {
router.fallback_service(serve_dir.fallback(get(|| async move {
"The requested path does not exist"
.to_string()
.into_response()
})))
};
let listener = tokio::net::TcpListener::bind(serve_address).await.unwrap();
axum::serve(listener, router.into_make_service())
.await
.unwrap();
}
});
#[cfg(not(feature = "server"))]
{
#[cfg(feature = "web")]
{
let cfg = platform_config.web_cfg.hydrate(true);
dioxus_web::launch::launch_virtual_dom(virtual_dom_factory(), cfg);
}
}
}
+5
View File
@@ -16,3 +16,8 @@ pub(crate) mod ssg;
pub mod prelude {
pub use dioxus_fullstack::prelude::*;
}
/// A document provider for static generation apps
pub mod document {
pub use dioxus_fullstack::document::*;
}
+11 -7
View File
@@ -4,7 +4,7 @@ use dioxus_router::prelude::*;
use dioxus_ssr::renderer;
use std::collections::HashSet;
use std::fs;
use std::path::Path;
use std::path::{Path, PathBuf};
use crate::Config;
@@ -65,20 +65,24 @@ pub async fn generate_static_site(
}
// Copy over the web output dir into the static output dir
let assets_path = dioxus_cli_config::out_dir().unwrap_or("./dist".into());
let out_path = dioxus_cli_config::out_dir().unwrap_or("./dist".into());
let assets_path = assets_path.join("public");
let assets_path = out_path.join("public");
copy_static_files(&assets_path, &config.output_dir)?;
let index_path = assets_path.join("index.html");
let skip = vec![index_path.clone()];
copy_static_files(&assets_path, &config.output_dir, &skip)?;
// Copy the output of the SSG build into the public directory so the CLI serves it
copy_static_files(&config.output_dir, &assets_path, &[])?;
Ok(())
}
fn copy_static_files(src: &Path, dst: &Path) -> Result<(), std::io::Error> {
let index_path = src.join("index.html");
fn copy_static_files(src: &Path, dst: &Path, skip: &[PathBuf]) -> Result<(), std::io::Error> {
let mut queue = vec![src.to_path_buf()];
while let Some(path) = queue.pop() {
if path == index_path {
if skip.contains(&path) {
continue;
}
if path.is_dir() {