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:
1 parent
2d7bef44e8
commit
20d146d9bd
126 files changed
+618
-989
No files matched your search
@@ -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")]
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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::*;
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
Reference in new issue
Block a user