mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-22 04:03:04 +00:00
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:
parent
2d7bef44e8
commit
20d146d9bd
126 changed files with 618 additions and 989 deletions
|
@ -0,0 +1 @@
|
|||
|
|
@ -15,7 +15,7 @@ mod components {
|
|||
mod api;
|
||||
|
||||
fn main() {
|
||||
launch(|| {
|
||||
dioxus::launch(|| {
|
||||
rsx! {
|
||||
head::Link {
|
||||
rel: "stylesheet",
|
||||
|
|
|
@ -12,7 +12,7 @@ use dioxus::desktop::{Config, WindowBuilder};
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::desktop()
|
||||
dioxus::LaunchBuilder::desktop()
|
||||
.with_cfg(Config::new().with_window(WindowBuilder::new().with_resizable(true)))
|
||||
.launch(app)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ fn main() {
|
|||
#[cfg(feature = "server")]
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
launch(|| rsx! { Router::<Route> {} });
|
||||
dioxus::launch(|| rsx! { Router::<Route> {} });
|
||||
}
|
||||
|
||||
#[derive(Clone, Routable)]
|
||||
|
|
|
@ -2,7 +2,7 @@ use dioxus::prelude::*;
|
|||
use wifiscanner::Wifi;
|
||||
|
||||
fn main() {
|
||||
launch(app)
|
||||
dioxus::launch(app)
|
||||
}
|
||||
|
||||
fn perform_scan() -> Status {
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::{collections::VecDeque, fmt::Debug, rc::Rc};
|
|||
const STYLE: &str = asset!("./examples/assets/events.css");
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -11,7 +11,7 @@ use async_std::task::sleep;
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -15,7 +15,7 @@ use dioxus::prelude::*;
|
|||
const STYLE: &str = asset!("./examples/assets/calculator.css");
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::desktop()
|
||||
dioxus::LaunchBuilder::desktop()
|
||||
.with_cfg(desktop!({
|
||||
use dioxus::desktop::{Config, LogicalSize, WindowBuilder};
|
||||
Config::new().with_window(
|
||||
|
|
|
@ -13,7 +13,7 @@ use dioxus::html::MouseEvent;
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::desktop()
|
||||
dioxus::LaunchBuilder::desktop()
|
||||
.with_cfg(
|
||||
Config::new().with_window(
|
||||
WindowBuilder::new()
|
||||
|
|
|
@ -8,7 +8,7 @@ use web_time::Instant;
|
|||
const STYLE: &str = asset!("./examples/assets/clock.css");
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -11,7 +11,7 @@ use dioxus::prelude::*;
|
|||
const STYLE: &str = asset!("./examples/assets/roulette.css");
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -5,7 +5,7 @@ use dioxus::prelude::*;
|
|||
const STYLE: &str = asset!("./examples/assets/counter.css");
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::new()
|
||||
dioxus::LaunchBuilder::new()
|
||||
.with_cfg(desktop!({
|
||||
use dioxus::desktop::{LogicalSize, WindowBuilder};
|
||||
dioxus::desktop::Config::default()
|
||||
|
|
|
@ -14,7 +14,7 @@ static ASSET_PATH: &str = "examples/assets/logo.png";
|
|||
static ASSET_PATH: &str = asset!("examples/assets/logo.png".format(ImageType::Avif));
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::new()
|
||||
dioxus::LaunchBuilder::new()
|
||||
.with_cfg(
|
||||
dioxus::desktop::Config::new().with_custom_index(
|
||||
r#"
|
||||
|
|
|
@ -28,7 +28,7 @@ fn main() {
|
|||
let config = dioxus::desktop::Config::new().with_menu(menu);
|
||||
|
||||
// Launch the app with the custom menu
|
||||
LaunchBuilder::new().with_cfg(config).launch(app)
|
||||
dioxus::LaunchBuilder::new().with_cfg(config).launch(app)
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -11,7 +11,7 @@ use dioxus::prelude::*;
|
|||
use std::collections::HashMap;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -10,7 +10,7 @@ use dioxus::prelude::*;
|
|||
const STYLE: &str = asset!("./examples/assets/custom_assets.css");
|
||||
|
||||
fn main() {
|
||||
launch_desktop(app);
|
||||
dioxus::LaunchBuilder::desktop().launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(|| rsx! { Router::<Route> {} });
|
||||
dioxus::launch(|| rsx! { Router::<Route> {} });
|
||||
}
|
||||
|
||||
/// You can use an ErrorBoundary to catch errors in children and display a warning
|
||||
|
|
|
@ -7,7 +7,7 @@ use async_std::task::sleep;
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -11,7 +11,7 @@ use dioxus::{html::HasFileData, prelude::dioxus_elements::FileEngine};
|
|||
const STYLE: &str = asset!("./examples/assets/file_upload.css");
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
struct UploadedFile {
|
||||
|
|
|
@ -12,7 +12,7 @@ use dioxus::prelude::*;
|
|||
const STYLE: &str = asset!("./examples/assets/flat_router.css");
|
||||
|
||||
fn main() {
|
||||
launch(|| {
|
||||
dioxus::launch(|| {
|
||||
rsx! {
|
||||
head::Link { rel: "stylesheet", href: STYLE }
|
||||
Router::<Route> {}
|
||||
|
|
|
@ -7,7 +7,7 @@ use dioxus::prelude::*;
|
|||
use std::collections::HashMap;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -5,7 +5,7 @@ fn main() {
|
|||
// Set the url of the server where server functions are hosted.
|
||||
#[cfg(not(feature = "server"))]
|
||||
dioxus::fullstack::prelude::server_fn::client::set_server_url("http://127.0.0.1:8080");
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
pub fn app() -> Element {
|
||||
|
|
|
@ -50,5 +50,5 @@ fn main() {
|
|||
#[cfg(feature = "server")]
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::fullstack()
|
||||
dioxus::LaunchBuilder::new()
|
||||
.with_cfg(server_only!(ServeConfig::builder().incremental(
|
||||
IncrementalRendererConfig::default()
|
||||
.invalidate_after(std::time::Duration::from_secs(120)),
|
||||
|
|
|
@ -37,5 +37,5 @@ pub async fn test_stream() -> Result<TextStream, ServerFnError> {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
launch(app)
|
||||
dioxus::launch(app)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use async_std::task::sleep;
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -7,7 +7,7 @@ use dioxus::prelude::*;
|
|||
use std::fmt::Display;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -13,7 +13,7 @@ static COUNT: GlobalSignal<i32> = Signal::global(|| 0);
|
|||
static DOUBLED_COUNT: GlobalMemo<i32> = Memo::global(|| COUNT() * 2);
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -19,7 +19,7 @@ use dioxus::prelude::*;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
fn main() {
|
||||
launch(|| {
|
||||
dioxus::launch(|| {
|
||||
rsx! {
|
||||
Router::<Route> {}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -13,7 +13,7 @@ use dioxus::desktop::Config;
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::desktop()
|
||||
dioxus::LaunchBuilder::desktop()
|
||||
.with_cfg(Config::new().with_prerendered({
|
||||
// We build the dom a first time, then pre-render it to HTML
|
||||
let pre_rendered_dom = VirtualDom::prebuilt(app);
|
||||
|
|
|
@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
|||
use serde_json::{json, Error};
|
||||
|
||||
fn main() {
|
||||
launch(app)
|
||||
dioxus::launch(app)
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -11,7 +11,7 @@ use dioxus::prelude::*;
|
|||
const STYLE: &str = asset!("./examples/assets/links.css");
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -4,7 +4,7 @@ use dioxus::prelude::*;
|
|||
|
||||
fn main() {
|
||||
tracing_subscriber::fmt::init();
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -50,7 +50,7 @@ pub fn main() -> Result<()> {
|
|||
|
||||
// Right now we're going through dioxus-desktop but we'd like to go through dioxus-mobile
|
||||
// That will seed the index.html with some fixes that prevent the page from scrolling/zooming etc
|
||||
LaunchBuilder::mobile()
|
||||
dioxus::LaunchBuilder::mobile()
|
||||
.with_cfg(
|
||||
// Note that we have to disable the viewport goofiness of the browser.
|
||||
// Dioxus_mobile should do this for us
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch_desktop(app);
|
||||
dioxus::LaunchBuilder::desktop().launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -11,7 +11,9 @@ use dioxus::desktop::{
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::desktop().with_cfg(make_config()).launch(app);
|
||||
dioxus::LaunchBuilder::desktop()
|
||||
.with_cfg(make_config())
|
||||
.launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -5,7 +5,7 @@ use dioxus::prelude::*;
|
|||
use std::rc::Rc;
|
||||
|
||||
fn main() {
|
||||
launch_desktop(app);
|
||||
dioxus::LaunchBuilder::desktop().launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -5,7 +5,7 @@ fn main() {
|
|||
wasm_logger::init(wasm_logger::Config::default());
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(|| {
|
||||
dioxus::launch(|| {
|
||||
rsx! {
|
||||
Router::<Route> {}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::rc::Rc;
|
|||
use dioxus::{html::geometry::euclid::Rect, prelude::*};
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -10,7 +10,7 @@ use dioxus::prelude::*;
|
|||
const STYLE: &str = asset!("./examples/assets/radio.css");
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -8,7 +8,7 @@ use dioxus::prelude::*;
|
|||
use dioxus_elements::geometry::euclid::Size2D;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -11,7 +11,7 @@ use dioxus::prelude::*;
|
|||
const STYLE: &str = asset!("./examples/assets/router.css");
|
||||
|
||||
fn main() {
|
||||
launch(|| {
|
||||
dioxus::launch(|| {
|
||||
rsx! {
|
||||
head::Link { rel: "stylesheet", href: STYLE }
|
||||
Router::<Route> {}
|
||||
|
|
|
@ -15,7 +15,7 @@ enum Route {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
launch(App);
|
||||
dioxus::launch(App);
|
||||
}
|
||||
|
||||
#[component]
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
//! - Allow top-level fragments
|
||||
|
||||
fn main() {
|
||||
launch(app)
|
||||
dioxus::launch(app)
|
||||
}
|
||||
|
||||
use core::{fmt, str::FromStr};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -9,7 +9,7 @@ use dioxus::desktop::use_global_shortcut;
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch_desktop(app);
|
||||
dioxus::LaunchBuilder::desktop().launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -10,7 +10,7 @@ use async_std::task::sleep;
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
// Launch the router, using our `Route` component as the generic type
|
||||
// launch the router, using our `Route` component as the generic type
|
||||
// This will automatically boot the app to "/" unless otherwise specified
|
||||
launch(|| rsx! { Router::<Route> {} });
|
||||
dioxus::launch(|| rsx! { Router::<Route> {} });
|
||||
}
|
||||
|
||||
/// By default, the Routable derive will use the name of the variant as the route
|
||||
|
|
|
@ -6,7 +6,7 @@ use dioxus::prelude::*;
|
|||
|
||||
// Generate all routes and output them to the static path
|
||||
fn main() {
|
||||
LaunchBuilder::new()
|
||||
dioxus::LaunchBuilder::new()
|
||||
.with_cfg(dioxus::static_site_generation::Config::new().github_pages())
|
||||
.launch(|| {
|
||||
rsx! {
|
||||
|
|
|
@ -5,7 +5,7 @@ use dioxus::prelude::*;
|
|||
|
||||
// Generate all routes and output them to the static path
|
||||
fn main() {
|
||||
launch(|| {
|
||||
dioxus::launch(|| {
|
||||
rsx! {
|
||||
Router::<Route> {}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use dioxus::prelude::*;
|
|||
|
||||
// Generate all routes and output them to the static path
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -5,7 +5,7 @@ use dioxus::prelude::*;
|
|||
use futures_util::{future, stream, Stream, StreamExt};
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -15,7 +15,7 @@ use dioxus::desktop::{Config, LogicalSize, WindowBuilder};
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::new()
|
||||
dioxus::LaunchBuilder::new()
|
||||
.with_cfg(desktop! {
|
||||
Config::new().with_window(
|
||||
WindowBuilder::new()
|
||||
|
|
|
@ -10,7 +10,7 @@ use dioxus::prelude::*;
|
|||
use rand::{thread_rng, Rng};
|
||||
|
||||
fn main() {
|
||||
launch(|| {
|
||||
dioxus::launch(|| {
|
||||
rsx! {
|
||||
div { user_select: "none", webkit_user_select: "none", margin_left: "10%", margin_right: "10%",
|
||||
h1 { "Click die to generate a new value" }
|
||||
|
|
|
@ -5,7 +5,7 @@ use dioxus::prelude::*;
|
|||
const _STYLE: &str = asset!("public/tailwind.css");
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
pub fn app() -> Element {
|
||||
|
|
|
@ -4,7 +4,7 @@ use dioxus::prelude::*;
|
|||
|
||||
fn main() {
|
||||
tracing_subscriber::fmt::init();
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::collections::HashMap;
|
|||
const STYLE: &str = asset!("./examples/assets/todomvc.css");
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
|
|
|
@ -16,13 +16,13 @@ fn main() {
|
|||
// For the sake of this example, we will download the video file if it doesn't exist
|
||||
ensure_video_is_loaded();
|
||||
|
||||
launch_desktop(app);
|
||||
dioxus::LaunchBuilder::desktop().launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
// Any request to /videos will be handled by this handler
|
||||
use_asset_handler("videos", move |request, responder| {
|
||||
// Using dioxus::spawn works, but is slower than a dedicated thread
|
||||
// Using spawn works, but is slower than a dedicated thread
|
||||
tokio::task::spawn(async move {
|
||||
let video_file = PathBuf::from(VIDEO_PATH);
|
||||
let mut file = tokio::fs::File::open(&video_file).await.unwrap();
|
||||
|
|
|
@ -4,7 +4,7 @@ use dioxus::prelude::*;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -13,7 +13,7 @@ use dioxus::desktop::{window, Config, WindowBuilder};
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::desktop()
|
||||
dioxus::LaunchBuilder::desktop()
|
||||
.with_cfg(
|
||||
Config::new().with_window(
|
||||
WindowBuilder::new()
|
||||
|
|
|
@ -12,7 +12,7 @@ use dioxus::desktop::{Config, WindowCloseBehaviour};
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::desktop()
|
||||
dioxus::LaunchBuilder::desktop()
|
||||
.with_cfg(Config::new().with_close_behaviour(WindowCloseBehaviour::CloseWindow))
|
||||
.launch(app)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch_desktop(app);
|
||||
dioxus::LaunchBuilder::desktop().launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(app);
|
||||
dioxus::launch(app);
|
||||
}
|
||||
|
||||
fn app() -> Element {
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::{
|
|||
use tokio::time::sleep;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::desktop().launch(app);
|
||||
dioxus::LaunchBuilder::desktop().launch(app);
|
||||
}
|
||||
|
||||
struct WindowPreferences {
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::{
|
|||
use tokio::time::sleep;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::desktop().launch(app);
|
||||
dioxus::LaunchBuilder::desktop().launch(app);
|
||||
}
|
||||
|
||||
struct WindowPreferences {
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::{
|
|||
use tokio::time::sleep;
|
||||
|
||||
fn main() {
|
||||
LaunchBuilder::desktop().launch(app);
|
||||
dioxus::LaunchBuilder::desktop().launch(app);
|
||||
}
|
||||
|
||||
struct WindowPreferences {
|
||||
|
|
|
@ -150,6 +150,49 @@ impl BuildRequest {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub(crate) struct OpenArguments {
|
||||
fullstack_address: Option<SocketAddr>,
|
||||
devserver_addr: Option<SocketAddr>,
|
||||
always_on_top: Option<bool>,
|
||||
workspace: PathBuf,
|
||||
asset_root: PathBuf,
|
||||
app_title: String,
|
||||
out_dir: PathBuf,
|
||||
serve: bool,
|
||||
}
|
||||
|
||||
impl OpenArguments {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn new(
|
||||
serve: &ServeArguments,
|
||||
fullstack_address: Option<SocketAddr>,
|
||||
dioxus_crate: &DioxusCrate,
|
||||
) -> Self {
|
||||
Self {
|
||||
devserver_addr: Some(serve.address.address()),
|
||||
always_on_top: Some(serve.always_on_top.unwrap_or(true)),
|
||||
serve: true,
|
||||
fullstack_address,
|
||||
workspace: dioxus_crate.workspace_dir().to_path_buf(),
|
||||
asset_root: dioxus_crate.asset_dir().to_path_buf(),
|
||||
app_title: dioxus_crate.dioxus_config.application.name.clone(),
|
||||
out_dir: dioxus_crate.out_dir().to_path_buf(),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn new_for_static_generation_build(dioxus_crate: &DioxusCrate) -> Self {
|
||||
Self {
|
||||
workspace: dioxus_crate.workspace_dir().to_path_buf(),
|
||||
asset_root: dioxus_crate.asset_dir().to_path_buf(),
|
||||
app_title: dioxus_crate.dioxus_config.application.name.clone(),
|
||||
out_dir: dioxus_crate.out_dir().to_path_buf(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct BuildResult {
|
||||
pub executable: PathBuf,
|
||||
|
@ -158,20 +201,12 @@ pub(crate) struct BuildResult {
|
|||
|
||||
impl BuildResult {
|
||||
/// Open the executable if this is a native build
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn open(
|
||||
&self,
|
||||
serve: &ServeArguments,
|
||||
fullstack_address: Option<SocketAddr>,
|
||||
workspace: &std::path::Path,
|
||||
asset_root: &std::path::Path,
|
||||
devserver_addr: SocketAddr,
|
||||
app_title: String,
|
||||
out_dir: PathBuf,
|
||||
) -> std::io::Result<Option<Child>> {
|
||||
pub fn open(&self, arguments: OpenArguments) -> std::io::Result<Option<Child>> {
|
||||
match self.target_platform {
|
||||
TargetPlatform::Web => {
|
||||
tracing::info!(dx_src = ?TraceSrc::Dev, "Serving web app on http://{} 🎉", serve.address.address());
|
||||
if let Some(address) = arguments.fullstack_address {
|
||||
tracing::info!(dx_src = ?TraceSrc::Dev, "Serving web app on http://{} 🎉", address);
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
TargetPlatform::Desktop => {
|
||||
|
@ -181,7 +216,7 @@ impl BuildResult {
|
|||
// shut this up for now - the web app will take priority in logging
|
||||
}
|
||||
TargetPlatform::Liveview => {
|
||||
if let Some(fullstack_address) = fullstack_address {
|
||||
if let Some(fullstack_address) = arguments.fullstack_address {
|
||||
tracing::info!(
|
||||
dx_src = ?TraceSrc::Dev,
|
||||
"Launching liveview server on http://{:?} 🎉",
|
||||
|
@ -191,7 +226,9 @@ impl BuildResult {
|
|||
}
|
||||
}
|
||||
|
||||
if arguments.serve {
|
||||
tracing::info!(dx_src = ?TraceSrc::Dev, "Press [o] to open the app manually.");
|
||||
}
|
||||
|
||||
let executable = self.executable.canonicalize()?;
|
||||
let mut cmd = Command::new(executable);
|
||||
|
@ -199,29 +236,36 @@ impl BuildResult {
|
|||
// Set the env vars that the clients will expect
|
||||
// These need to be stable within a release version (ie 0.6.0)
|
||||
cmd.env(dioxus_cli_config::CLI_ENABLED_ENV, "true");
|
||||
if let Some(addr) = fullstack_address {
|
||||
if let Some(addr) = arguments.fullstack_address {
|
||||
cmd.env(dioxus_cli_config::SERVER_IP_ENV, addr.ip().to_string());
|
||||
cmd.env(dioxus_cli_config::SERVER_PORT_ENV, addr.port().to_string());
|
||||
}
|
||||
if let Some(always_on_top) = arguments.always_on_top {
|
||||
cmd.env(
|
||||
dioxus_cli_config::ALWAYS_ON_TOP_ENV,
|
||||
serve.always_on_top.unwrap_or(true).to_string(),
|
||||
always_on_top.to_string(),
|
||||
);
|
||||
}
|
||||
cmd.env(
|
||||
dioxus_cli_config::ASSET_ROOT_ENV,
|
||||
asset_root.display().to_string(),
|
||||
arguments.asset_root.display().to_string(),
|
||||
);
|
||||
if let Some(devserver_addr) = arguments.devserver_addr {
|
||||
cmd.env(
|
||||
dioxus_cli_config::DEVSERVER_RAW_ADDR_ENV,
|
||||
devserver_addr.to_string(),
|
||||
);
|
||||
cmd.env(dioxus_cli_config::APP_TITLE_ENV, app_title);
|
||||
cmd.env(dioxus_cli_config::OUT_DIR, out_dir.display().to_string());
|
||||
}
|
||||
cmd.env(dioxus_cli_config::APP_TITLE_ENV, arguments.app_title);
|
||||
cmd.env(
|
||||
dioxus_cli_config::OUT_DIR,
|
||||
arguments.out_dir.display().to_string(),
|
||||
);
|
||||
|
||||
cmd.stderr(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.kill_on_drop(true)
|
||||
.current_dir(workspace);
|
||||
.current_dir(arguments.workspace);
|
||||
|
||||
Ok(Some(cmd.spawn()?))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use crate::config::Platform;
|
||||
use crate::{builder::OpenArguments, config::Platform};
|
||||
use anyhow::Context;
|
||||
|
||||
use crate::{
|
||||
|
@ -115,7 +115,20 @@ impl Build {
|
|||
pub async fn build(&mut self, dioxus_crate: &mut DioxusCrate) -> Result<()> {
|
||||
self.resolve(dioxus_crate)?;
|
||||
let build_requests = BuildRequest::create(false, dioxus_crate, self.clone())?;
|
||||
BuildRequest::build_all_parallel(build_requests).await?;
|
||||
let builds = BuildRequest::build_all_parallel(build_requests).await?;
|
||||
|
||||
// If this is a static generation build, building involves running the server to generate static files
|
||||
if self.platform.unwrap() == Platform::StaticGeneration {
|
||||
println!("Building static site...");
|
||||
for build in builds {
|
||||
if let Some(mut result) =
|
||||
build.open(OpenArguments::new_for_static_generation_build(dioxus_crate))?
|
||||
{
|
||||
result.wait().await?;
|
||||
}
|
||||
}
|
||||
println!("Static site built!");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::future::{poll_fn, Future, IntoFuture};
|
||||
use std::task::Poll;
|
||||
|
||||
use crate::builder::OpenArguments;
|
||||
use crate::cli::serve::Serve;
|
||||
use crate::dioxus_crate::DioxusCrate;
|
||||
use crate::tracer::CLILogControl;
|
||||
|
@ -156,23 +157,14 @@ pub async fn serve_all(
|
|||
builder.children.clear();
|
||||
}
|
||||
|
||||
let asset_dir = dioxus_crate
|
||||
.dioxus_config
|
||||
.application
|
||||
.asset_dir
|
||||
.canonicalize()
|
||||
.unwrap_or(std::path::PathBuf::from("./assets"));
|
||||
|
||||
// If we have a build result, open it
|
||||
for build_result in results.iter() {
|
||||
let child = build_result.open(
|
||||
OpenArguments::new(
|
||||
&serve.server_arguments,
|
||||
server.fullstack_address(),
|
||||
&dioxus_crate.workspace_dir(),
|
||||
&asset_dir,
|
||||
server.ip,
|
||||
dioxus_crate.dioxus_config.application.name.clone(),
|
||||
dioxus_crate.out_dir()
|
||||
&dioxus_crate
|
||||
)
|
||||
);
|
||||
match child {
|
||||
Ok(Some(child_proc)) => builder.children.push((build_result.target_platform, child_proc)),
|
||||
|
@ -192,12 +184,12 @@ pub async fn serve_all(
|
|||
server.send_reload_command().await;
|
||||
},
|
||||
|
||||
// If the process exited *cleanly*, we can exit
|
||||
// If the desktop process exited *cleanly*, we can exit
|
||||
Ok(BuilderUpdate::ProcessExited { status, target_platform }) => {
|
||||
// Then remove the child process
|
||||
builder.children.retain(|(platform, _)| *platform != target_platform);
|
||||
match status {
|
||||
Ok(status) => {
|
||||
match (target_platform, status) {
|
||||
(TargetPlatform::Desktop, Ok(status)) => {
|
||||
if status.success() {
|
||||
break;
|
||||
}
|
||||
|
@ -205,7 +197,9 @@ pub async fn serve_all(
|
|||
tracing::error!(dx_src = ?TraceSrc::Dev, "Application exited with status: {status}");
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
// Ignore the static generation platform exiting
|
||||
(_ , Ok(_)) => {},
|
||||
(_, Err(e)) => {
|
||||
tracing::error!(dx_src = ?TraceSrc::Dev, "Application exited with error: {e}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ impl Server {
|
|||
// If we're serving a fullstack app, we need to find a port to proxy to
|
||||
let fullstack_port = if matches!(
|
||||
serve.build_arguments.platform(),
|
||||
Platform::Liveview | Platform::Fullstack | Platform::StaticGeneration
|
||||
Platform::Liveview | Platform::Fullstack
|
||||
) {
|
||||
get_available_port(addr.ip())
|
||||
} else {
|
||||
|
@ -368,7 +368,7 @@ fn setup_router(
|
|||
|
||||
// server the dir if it's web, otherwise let the fullstack server itself handle it
|
||||
match platform {
|
||||
Platform::Web => {
|
||||
Platform::Web | Platform::StaticGeneration => {
|
||||
// Route file service to output the .wasm and assets if this is a web build
|
||||
let base_path = format!(
|
||||
"/{}",
|
||||
|
@ -382,9 +382,9 @@ fn setup_router(
|
|||
.trim_matches('/')
|
||||
);
|
||||
|
||||
router = router.nest_service(&base_path, build_serve_dir(serve, config));
|
||||
router = router.nest_service(&base_path, build_serve_dir(serve, config, platform));
|
||||
}
|
||||
Platform::Liveview | Platform::Fullstack | Platform::StaticGeneration => {
|
||||
Platform::Liveview | Platform::Fullstack => {
|
||||
// For fullstack and static generation, forward all requests to the server
|
||||
let address = fullstack_address.unwrap();
|
||||
|
||||
|
@ -449,7 +449,11 @@ fn setup_router(
|
|||
Ok(router)
|
||||
}
|
||||
|
||||
fn build_serve_dir(serve: &Serve, cfg: &DioxusCrate) -> axum::routing::MethodRouter {
|
||||
fn build_serve_dir(
|
||||
serve: &Serve,
|
||||
cfg: &DioxusCrate,
|
||||
platform: Platform,
|
||||
) -> axum::routing::MethodRouter {
|
||||
static CORS_UNSAFE: (HeaderValue, HeaderValue) = (
|
||||
HeaderValue::from_static("unsafe-none"),
|
||||
HeaderValue::from_static("unsafe-none"),
|
||||
|
@ -465,7 +469,11 @@ fn build_serve_dir(serve: &Serve, cfg: &DioxusCrate) -> axum::routing::MethodRou
|
|||
false => CORS_UNSAFE.clone(),
|
||||
};
|
||||
|
||||
let out_dir = cfg.out_dir();
|
||||
let out_dir = match platform {
|
||||
// Static generation only serves files from the public directory
|
||||
Platform::StaticGeneration => cfg.out_dir().join("public"),
|
||||
_ => cfg.out_dir(),
|
||||
};
|
||||
let index_on_404 = cfg.dioxus_config.web.watcher.index_on_404;
|
||||
|
||||
get_service(
|
||||
|
@ -479,7 +487,7 @@ fn build_serve_dir(serve: &Serve, cfg: &DioxusCrate) -> axum::routing::MethodRou
|
|||
let out_dir = out_dir.clone();
|
||||
move |response| async move { Ok(no_cache(index_on_404, &out_dir, response)) }
|
||||
})
|
||||
.service(ServeDir::new(out_dir)),
|
||||
.service(ServeDir::new(&out_dir)),
|
||||
)
|
||||
.handle_error(|error: Infallible| async move {
|
||||
(
|
||||
|
@ -500,7 +508,18 @@ fn no_cache(
|
|||
// If there's a 404 and we're supposed to index on 404, upgrade that failed request to the index.html
|
||||
// We might want to isnert a header here saying we *did* that but oh well
|
||||
if response.status() == StatusCode::NOT_FOUND && index_on_404 {
|
||||
let body = Body::from(std::fs::read_to_string(out_dir.join("index.html")).unwrap());
|
||||
// First try to find a 404.html or 404/index.html file
|
||||
let out_dir_404_html = out_dir.join("404.html");
|
||||
let out_dir_404_index_html = out_dir.join("404").join("index.html");
|
||||
let path = if out_dir_404_html.exists() {
|
||||
out_dir_404_html
|
||||
} else if out_dir_404_index_html.exists() {
|
||||
out_dir_404_index_html
|
||||
} else {
|
||||
// If we can't find a 404.html or 404/index.html, just use the index.html
|
||||
out_dir.join("index.html")
|
||||
};
|
||||
let body = Body::from(std::fs::read_to_string(path).unwrap());
|
||||
|
||||
response = Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
|
|
8
packages/core/src/launch.rs
Normal file
8
packages/core/src/launch.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
//! This module contains utilities renderers use to integrate with the launch function.
|
||||
|
||||
/// A marker trait for platform configs. We use this marker to
|
||||
/// make sure that the user doesn't accidentally pass in a config
|
||||
/// builder instead of the config
|
||||
pub trait LaunchConfig: 'static {}
|
||||
|
||||
impl LaunchConfig for () {}
|
|
@ -12,6 +12,7 @@ mod events;
|
|||
mod fragment;
|
||||
mod generational_box;
|
||||
mod global_context;
|
||||
mod launch;
|
||||
mod mutations;
|
||||
mod nodes;
|
||||
mod properties;
|
||||
|
@ -51,6 +52,7 @@ pub(crate) mod innerlude {
|
|||
pub use crate::fragment::*;
|
||||
pub use crate::generational_box::*;
|
||||
pub use crate::global_context::*;
|
||||
pub use crate::launch::*;
|
||||
pub use crate::mutations::*;
|
||||
pub use crate::nodes::*;
|
||||
pub use crate::properties::*;
|
||||
|
@ -75,10 +77,10 @@ pub(crate) mod innerlude {
|
|||
pub use crate::innerlude::{
|
||||
fc_to_builder, generation, schedule_update, schedule_update_any, use_hook, vdom_is_rendering,
|
||||
AnyValue, Attribute, AttributeValue, CapturedError, Component, ComponentFunction, DynamicNode,
|
||||
Element, ElementId, Event, Fragment, HasAttributes, IntoDynNode, MarkerWrapper, Mutation,
|
||||
Mutations, NoOpMutations, Ok, Properties, Result, Runtime, ScopeId, ScopeState, SpawnIfAsync,
|
||||
Task, Template, TemplateAttribute, TemplateNode, VComponent, VNode, VNodeInner, VPlaceholder,
|
||||
VText, VirtualDom, WriteMutations,
|
||||
Element, ElementId, Event, Fragment, HasAttributes, IntoDynNode, LaunchConfig, MarkerWrapper,
|
||||
Mutation, Mutations, NoOpMutations, Ok, Properties, Result, Runtime, ScopeId, ScopeState,
|
||||
SpawnIfAsync, Task, Template, TemplateAttribute, TemplateNode, VComponent, VNode, VNodeInner,
|
||||
VPlaceholder, VText, VirtualDom, WriteMutations,
|
||||
};
|
||||
|
||||
/// The purpose of this module is to alleviate imports of many common types
|
||||
|
|
|
@ -17,7 +17,7 @@ pub fn check_app_exits(app: fn() -> Element) {
|
|||
}
|
||||
});
|
||||
|
||||
LaunchBuilder::desktop()
|
||||
dioxus::LaunchBuilder::desktop()
|
||||
.with_cfg(Config::new().with_window(WindowBuilder::new().with_visible(false)))
|
||||
.launch(app);
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use dioxus_core::LaunchConfig;
|
||||
use std::borrow::Cow;
|
||||
use std::path::PathBuf;
|
||||
use tao::window::{Icon, WindowBuilder};
|
||||
|
@ -51,6 +52,8 @@ pub struct Config {
|
|||
pub(crate) last_window_close_behavior: WindowCloseBehaviour,
|
||||
}
|
||||
|
||||
impl LaunchConfig for Config {}
|
||||
|
||||
pub(crate) type WryProtocol = (
|
||||
String,
|
||||
Box<dyn Fn(HttpRequest<Vec<u8>>) -> HttpResponse<Cow<'static, [u8]>> + 'static>,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pub use crate::Config;
|
||||
use crate::Config;
|
||||
use crate::{
|
||||
app::App,
|
||||
ipc::{IpcMethod, UserWindowEvent},
|
||||
|
@ -82,8 +82,8 @@ pub fn launch_virtual_dom(virtual_dom: VirtualDom, desktop_config: Config) -> !
|
|||
/// Launches the WebView and runs the event loop, with configuration and root props.
|
||||
pub fn launch(
|
||||
root: fn() -> Element,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any>>>,
|
||||
platform_config: Config,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
|
||||
platform_config: Vec<Box<dyn Any>>,
|
||||
) -> ! {
|
||||
let mut virtual_dom = VirtualDom::new(root);
|
||||
|
||||
|
@ -91,5 +91,10 @@ pub fn launch(
|
|||
virtual_dom.insert_any_root_context(context());
|
||||
}
|
||||
|
||||
let platform_config = *platform_config
|
||||
.into_iter()
|
||||
.find_map(|cfg| cfg.downcast::<Config>().ok())
|
||||
.unwrap_or_default();
|
||||
|
||||
launch_virtual_dom(virtual_dom, platform_config)
|
||||
}
|
||||
|
|
|
@ -35,11 +35,11 @@ fn main() {
|
|||
}
|
||||
|
||||
fn app() -> Element {
|
||||
rsx!{
|
||||
rsx! {
|
||||
div {
|
||||
"hello world!"
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ To launch an app, we use the `launch` method and use features in `Cargo.toml` to
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(App);
|
||||
dioxus::launch(App);
|
||||
}
|
||||
|
||||
// The #[component] attribute streamlines component creation.
|
||||
|
@ -239,7 +239,7 @@ Using components, templates, and hooks, we can build a simple app.
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(App);
|
||||
dioxus::launch(App);
|
||||
}
|
||||
|
||||
#[component]
|
||||
|
|
|
@ -42,7 +42,7 @@ To launch an app, we use the `launch` method and use features in `Cargo.toml` to
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(App);
|
||||
dioxus::launch(App);
|
||||
}
|
||||
|
||||
// The #[component] attribute streamlines component creation.
|
||||
|
@ -184,7 +184,7 @@ Using components, rsx, and hooks, we can build a simple app.
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(App);
|
||||
dioxus::launch(App);
|
||||
}
|
||||
|
||||
#[component]
|
||||
|
|
|
@ -2,20 +2,22 @@
|
|||
#![allow(clippy::new_without_default)]
|
||||
#![allow(unused)]
|
||||
use dioxus_config_macro::*;
|
||||
use dioxus_core::LaunchConfig;
|
||||
use std::any::Any;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
/// A builder for a fullstack app.
|
||||
#[must_use]
|
||||
pub struct LaunchBuilder<Cfg: 'static = (), ContextFn: ?Sized = ValidContext> {
|
||||
launch_fn: LaunchFn<Cfg, ContextFn>,
|
||||
contexts: Vec<Box<ContextFn>>,
|
||||
|
||||
platform_config: Option<Cfg>,
|
||||
pub struct LaunchBuilder {
|
||||
launch_fn: LaunchFn,
|
||||
contexts: Vec<ContextFn>,
|
||||
configs: Vec<Box<dyn Any>>,
|
||||
}
|
||||
|
||||
pub type LaunchFn<Cfg, Context> = fn(fn() -> Element, Vec<Box<Context>>, Cfg);
|
||||
pub type LaunchFn = fn(fn() -> Element, Vec<ContextFn>, Vec<Box<dyn Any>>);
|
||||
/// A context function is a Send and Sync closure that returns a boxed trait object
|
||||
pub type ContextFn = Box<dyn Fn() -> Box<dyn Any> + Send + Sync + 'static>;
|
||||
|
||||
#[cfg(any(
|
||||
feature = "fullstack",
|
||||
|
@ -54,69 +56,74 @@ impl LaunchBuilder {
|
|||
note = "No renderer is enabled. You must enable a renderer feature on the dioxus crate before calling the launch function.\nAdd `web`, `desktop`, `mobile`, `fullstack`, or `static-generation` to the `features` of dioxus field in your Cargo.toml.\n# Example\n```toml\n# ...\n[dependencies]\ndioxus = { version = \"0.5.0\", features = [\"web\"] }\n# ...\n```"
|
||||
)
|
||||
)]
|
||||
pub fn new() -> LaunchBuilder<current_platform::Config, ValidContext> {
|
||||
pub fn new() -> LaunchBuilder {
|
||||
LaunchBuilder {
|
||||
// We can't use the `current_platform::launch` function directly because it may return ! or ()
|
||||
launch_fn: |root, contexts, cfg| current_platform::launch(root, contexts, cfg),
|
||||
contexts: Vec::new(),
|
||||
platform_config: None,
|
||||
configs: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Launch your web application.
|
||||
#[cfg(feature = "web")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "web")))]
|
||||
pub fn web() -> LaunchBuilder<dioxus_web::Config, UnsendContext> {
|
||||
pub fn web() -> LaunchBuilder {
|
||||
LaunchBuilder {
|
||||
launch_fn: dioxus_web::launch::launch,
|
||||
launch_fn: web_launch,
|
||||
contexts: Vec::new(),
|
||||
platform_config: None,
|
||||
configs: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Launch your desktop application.
|
||||
#[cfg(feature = "desktop")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "desktop")))]
|
||||
pub fn desktop() -> LaunchBuilder<dioxus_desktop::Config, UnsendContext> {
|
||||
pub fn desktop() -> LaunchBuilder {
|
||||
LaunchBuilder {
|
||||
launch_fn: |root, contexts, cfg| dioxus_desktop::launch::launch(root, contexts, cfg),
|
||||
contexts: Vec::new(),
|
||||
platform_config: None,
|
||||
configs: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Launch your fullstack application.
|
||||
#[cfg(feature = "fullstack")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "fullstack")))]
|
||||
pub fn fullstack() -> LaunchBuilder<dioxus_fullstack::Config, SendContext> {
|
||||
/// Launch your fullstack axum server.
|
||||
#[cfg(all(feature = "fullstack", feature = "server"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "fullstack", feature = "server"))))]
|
||||
pub fn server() -> LaunchBuilder {
|
||||
LaunchBuilder {
|
||||
launch_fn: |root, contexts, cfg| dioxus_fullstack::launch::launch(root, contexts, cfg),
|
||||
launch_fn: |root, contexts, cfg| {
|
||||
dioxus_fullstack::server::launch::launch(root, contexts, cfg)
|
||||
},
|
||||
contexts: Vec::new(),
|
||||
platform_config: None,
|
||||
configs: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Launch your static site generation application.
|
||||
#[cfg(feature = "static-generation")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "static-generation")))]
|
||||
pub fn static_generation() -> LaunchBuilder<dioxus_static_site_generation::Config, SendContext>
|
||||
{
|
||||
#[cfg(all(feature = "static-generation", feature = "server"))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(all(feature = "static-generation", feature = "server")))
|
||||
)]
|
||||
pub fn static_generation() -> LaunchBuilder {
|
||||
LaunchBuilder {
|
||||
launch_fn: |root, contexts, cfg| {
|
||||
dioxus_static_site_generation::launch::launch(root, contexts, cfg)
|
||||
},
|
||||
contexts: Vec::new(),
|
||||
platform_config: None,
|
||||
configs: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Launch your fullstack application.
|
||||
#[cfg(feature = "mobile")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "mobile")))]
|
||||
pub fn mobile() -> LaunchBuilder<dioxus_mobile::Config, UnsendContext> {
|
||||
pub fn mobile() -> LaunchBuilder {
|
||||
LaunchBuilder {
|
||||
launch_fn: |root, contexts, cfg| dioxus_mobile::launch::launch(root, contexts, cfg),
|
||||
contexts: Vec::new(),
|
||||
platform_config: None,
|
||||
configs: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,7 +139,7 @@ impl LaunchBuilder {
|
|||
/// #[derive(Default)]
|
||||
/// struct Config;
|
||||
///
|
||||
/// fn my_custom_launcher(root: fn() -> Element, contexts: Vec<Box<dyn Any>>, cfg: Config) {
|
||||
/// fn my_custom_launcher(root: fn() -> Element, contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>, cfg: Vec<Box<dyn Any>>) {
|
||||
/// println!("launching with root: {:?}", root());
|
||||
/// loop {
|
||||
/// println!("running...");
|
||||
|
@ -145,42 +152,24 @@ impl LaunchBuilder {
|
|||
/// }
|
||||
/// }
|
||||
///
|
||||
/// LaunchBuilder::custom(my_custom_launcher).launch(app);
|
||||
/// dioxus::LaunchBuilder::custom(my_custom_launcher).launch(app);
|
||||
/// ```
|
||||
pub fn custom<Config, Context: ?Sized>(
|
||||
launch_fn: LaunchFn<Config, Context>,
|
||||
) -> LaunchBuilder<Config, Context> {
|
||||
pub fn custom(launch_fn: LaunchFn) -> LaunchBuilder {
|
||||
LaunchBuilder {
|
||||
launch_fn,
|
||||
contexts: vec![],
|
||||
platform_config: None,
|
||||
configs: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fullstack platform builder
|
||||
impl<Cfg> LaunchBuilder<Cfg, UnsendContext> {
|
||||
/// Inject state into the root component's context that is created on the thread that the app is launched on.
|
||||
pub fn with_context_provider(mut self, state: impl Fn() -> Box<dyn Any> + 'static) -> Self {
|
||||
self.contexts.push(Box::new(state) as Box<UnsendContext>);
|
||||
self
|
||||
}
|
||||
|
||||
/// Inject state into the root component's context.
|
||||
pub fn with_context(mut self, state: impl Any + Clone + 'static) -> Self {
|
||||
self.contexts
|
||||
.push(Box::new(move || Box::new(state.clone())));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<Cfg> LaunchBuilder<Cfg, SendContext> {
|
||||
impl LaunchBuilder {
|
||||
/// Inject state into the root component's context that is created on the thread that the app is launched on.
|
||||
pub fn with_context_provider(
|
||||
mut self,
|
||||
state: impl Fn() -> Box<dyn Any + Send + Sync> + Send + Sync + 'static,
|
||||
state: impl Fn() -> Box<dyn Any> + Send + Sync + 'static,
|
||||
) -> Self {
|
||||
self.contexts.push(Box::new(state) as Box<SendContext>);
|
||||
self.contexts.push(Box::new(state));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -192,38 +181,10 @@ impl<Cfg> LaunchBuilder<Cfg, SendContext> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A trait for converting a type into a platform-specific config:
|
||||
/// - A unit value will be converted into `None`
|
||||
/// - Any config will be converted into `Some(config)`
|
||||
/// - If the config is for another platform, it will be converted into `None`
|
||||
pub trait TryIntoConfig<Config = Self> {
|
||||
fn into_config(self, config: &mut Option<Config>);
|
||||
}
|
||||
|
||||
// A config can always be converted into itself
|
||||
impl<Cfg> TryIntoConfig<Cfg> for Cfg {
|
||||
fn into_config(self, config: &mut Option<Cfg>) {
|
||||
*config = Some(self);
|
||||
}
|
||||
}
|
||||
|
||||
// The unit type can be converted into the current platform config.
|
||||
// This makes it possible to use the `desktop!`, `web!`, etc macros with the launch API.
|
||||
#[cfg(any(
|
||||
feature = "liveview",
|
||||
feature = "desktop",
|
||||
feature = "mobile",
|
||||
feature = "web",
|
||||
feature = "fullstack"
|
||||
))]
|
||||
impl TryIntoConfig<current_platform::Config> for () {
|
||||
fn into_config(self, config: &mut Option<current_platform::Config>) {}
|
||||
}
|
||||
|
||||
impl<Cfg: Default + 'static, ContextFn: ?Sized> LaunchBuilder<Cfg, ContextFn> {
|
||||
impl LaunchBuilder {
|
||||
/// Provide a platform-specific config to the builder.
|
||||
pub fn with_cfg(mut self, config: impl TryIntoConfig<Cfg>) -> Self {
|
||||
config.into_config(&mut self.platform_config);
|
||||
pub fn with_cfg(mut self, config: impl LaunchConfig) -> Self {
|
||||
self.configs.push(Box::new(config));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -231,7 +192,7 @@ impl<Cfg: Default + 'static, ContextFn: ?Sized> LaunchBuilder<Cfg, ContextFn> {
|
|||
#[cfg(any(feature = "static-generation", feature = "web"))]
|
||||
/// Launch your application.
|
||||
pub fn launch(self, app: fn() -> Element) {
|
||||
let cfg = self.platform_config.unwrap_or_default();
|
||||
let cfg = self.configs;
|
||||
|
||||
(self.launch_fn)(app, self.contexts, cfg)
|
||||
}
|
||||
|
@ -239,7 +200,7 @@ impl<Cfg: Default + 'static, ContextFn: ?Sized> LaunchBuilder<Cfg, ContextFn> {
|
|||
#[cfg(not(any(feature = "static-generation", feature = "web")))]
|
||||
/// Launch your application.
|
||||
pub fn launch(self, app: fn() -> Element) -> ! {
|
||||
let cfg = self.platform_config.unwrap_or_default();
|
||||
let cfg = self.configs;
|
||||
|
||||
(self.launch_fn)(app, self.contexts, cfg);
|
||||
unreachable!("Launching an application will never exit")
|
||||
|
@ -256,147 +217,67 @@ impl<Cfg: Default + 'static, ContextFn: ?Sized> LaunchBuilder<Cfg, ContextFn> {
|
|||
/// - `web`
|
||||
/// - `liveview`
|
||||
mod current_platform {
|
||||
macro_rules! if_else_cfg {
|
||||
(if $attr:meta { $($then:item)* } else { $($else:item)* }) => {
|
||||
$(
|
||||
#[cfg($attr)]
|
||||
$then
|
||||
)*
|
||||
$(
|
||||
#[cfg(not($attr))]
|
||||
$else
|
||||
)*
|
||||
};
|
||||
}
|
||||
use crate::prelude::TryIntoConfig;
|
||||
#[cfg(all(feature = "fullstack", feature = "server"))]
|
||||
pub use dioxus_fullstack::server::launch::*;
|
||||
|
||||
#[cfg(feature = "fullstack")]
|
||||
pub use dioxus_fullstack::launch::*;
|
||||
|
||||
#[cfg(all(feature = "fullstack", feature = "axum"))]
|
||||
impl TryIntoConfig<crate::launch::current_platform::Config>
|
||||
for ::dioxus_fullstack::prelude::ServeConfigBuilder
|
||||
{
|
||||
fn into_config(self, config: &mut Option<crate::launch::current_platform::Config>) {
|
||||
match config {
|
||||
Some(config) => config.set_server_config(self),
|
||||
None => {
|
||||
*config = Some(
|
||||
crate::launch::current_platform::Config::new().with_server_config(self),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "desktop", feature = "mobile"))]
|
||||
if_else_cfg! {
|
||||
if not(feature = "fullstack") {
|
||||
#[cfg(feature = "desktop")]
|
||||
#[cfg(all(
|
||||
feature = "desktop",
|
||||
not(all(feature = "fullstack", feature = "server"))
|
||||
))]
|
||||
pub use dioxus_desktop::launch::*;
|
||||
#[cfg(not(feature = "desktop"))]
|
||||
|
||||
#[cfg(all(
|
||||
feature = "mobile",
|
||||
not(feature = "desktop"),
|
||||
not(all(feature = "fullstack", feature = "server"))
|
||||
))]
|
||||
pub use dioxus_mobile::launch::*;
|
||||
} else {
|
||||
if_else_cfg! {
|
||||
if feature = "desktop" {
|
||||
impl TryIntoConfig<crate::launch::current_platform::Config> for ::dioxus_desktop::Config {
|
||||
fn into_config(self, config: &mut Option<crate::launch::current_platform::Config>) {
|
||||
match config {
|
||||
Some(config) => config.set_desktop_config(self),
|
||||
None => *config = Some(crate::launch::current_platform::Config::new().with_desktop_config(self)),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
impl TryIntoConfig<crate::launch::current_platform::Config> for ::dioxus_mobile::Config {
|
||||
fn into_config(self, config: &mut Option<crate::launch::current_platform::Config>) {
|
||||
match config {
|
||||
Some(config) => config.set_mobile_cfg(self),
|
||||
None => *config = Some(crate::launch::current_platform::Config::new().with_mobile_cfg(self)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "static-generation")]
|
||||
if_else_cfg! {
|
||||
if all(not(feature = "fullstack"), not(feature = "desktop"), not(feature = "mobile")) {
|
||||
#[cfg(all(
|
||||
all(feature = "static-generation", feature = "server"),
|
||||
not(all(feature = "fullstack", feature = "server")),
|
||||
not(feature = "desktop"),
|
||||
not(feature = "mobile")
|
||||
))]
|
||||
pub use dioxus_static_site_generation::launch::*;
|
||||
} else {
|
||||
impl TryIntoConfig<crate::launch::current_platform::Config> for ::dioxus_static_site_generation::Config {
|
||||
fn into_config(self, config: &mut Option<crate::launch::current_platform::Config>) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "web")]
|
||||
if_else_cfg! {
|
||||
if not(any(feature = "desktop", feature = "mobile", feature = "fullstack", feature = "static-generation")) {
|
||||
pub use dioxus_web::launch::*;
|
||||
} else {
|
||||
if_else_cfg! {
|
||||
if feature = "fullstack" {
|
||||
impl TryIntoConfig<crate::launch::current_platform::Config> for ::dioxus_web::Config {
|
||||
fn into_config(self, config: &mut Option<crate::launch::current_platform::Config>) {
|
||||
match config {
|
||||
Some(config) => config.set_web_config(self),
|
||||
None => *config = Some(crate::launch::current_platform::Config::new().with_web_config(self)),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
impl TryIntoConfig<crate::launch::current_platform::Config> for ::dioxus_web::Config {
|
||||
fn into_config(self, config: &mut Option<crate::launch::current_platform::Config>) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "liveview")]
|
||||
if_else_cfg! {
|
||||
if
|
||||
not(any(
|
||||
#[cfg(all(
|
||||
feature = "web",
|
||||
feature = "desktop",
|
||||
feature = "mobile",
|
||||
feature = "fullstack",
|
||||
feature = "static-generation"
|
||||
))
|
||||
{
|
||||
not(all(feature = "fullstack", feature = "server")),
|
||||
not(all(feature = "static-generation", feature = "server")),
|
||||
not(feature = "desktop"),
|
||||
not(feature = "mobile"),
|
||||
))]
|
||||
pub fn launch(
|
||||
root: fn() -> dioxus_core::Element,
|
||||
contexts: Vec<super::ContextFn>,
|
||||
platform_config: Vec<Box<dyn std::any::Any>>,
|
||||
) {
|
||||
super::web_launch(root, contexts, platform_config);
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "liveview",
|
||||
not(all(feature = "fullstack", feature = "server")),
|
||||
not(all(feature = "static-generation", feature = "server")),
|
||||
not(feature = "desktop"),
|
||||
not(feature = "mobile"),
|
||||
not(feature = "web"),
|
||||
))]
|
||||
pub use dioxus_liveview::launch::*;
|
||||
} else {
|
||||
impl<R: ::dioxus_liveview::LiveviewRouter> TryIntoConfig<crate::launch::current_platform::Config> for ::dioxus_liveview::Config<R> {
|
||||
fn into_config(self, config: &mut Option<crate::launch::current_platform::Config>) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
feature = "liveview",
|
||||
all(feature = "fullstack", feature = "server"),
|
||||
all(feature = "static-generation", feature = "server"),
|
||||
feature = "desktop",
|
||||
feature = "mobile",
|
||||
feature = "web",
|
||||
feature = "fullstack",
|
||||
feature = "static-generation"
|
||||
)))]
|
||||
pub type Config = ();
|
||||
|
||||
#[cfg(not(any(
|
||||
feature = "liveview",
|
||||
feature = "desktop",
|
||||
feature = "mobile",
|
||||
feature = "web",
|
||||
feature = "fullstack",
|
||||
feature = "static-generation"
|
||||
)))]
|
||||
pub fn launch(
|
||||
root: fn() -> dioxus_core::Element,
|
||||
contexts: Vec<Box<super::ValidContext>>,
|
||||
platform_config: (),
|
||||
contexts: Vec<super::ContextFn>,
|
||||
platform_config: Vec<Box<dyn std::any::Any>>,
|
||||
) -> ! {
|
||||
#[cfg(feature = "third-party-renderer")]
|
||||
panic!("No first party renderer feature enabled. It looks like you are trying to use a third party renderer. You will need to use the launch function from the third party renderer crate.");
|
||||
|
@ -409,22 +290,6 @@ mod current_platform {
|
|||
macro_rules! impl_launch {
|
||||
($($return_type:tt),*) => {
|
||||
/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
// If you aren't using a third party renderer and this is not a docs.rs build, generate a warning about no renderer being enabled
|
||||
#[cfg_attr(
|
||||
all(not(any(
|
||||
docsrs,
|
||||
feature = "third-party-renderer",
|
||||
feature = "liveview",
|
||||
feature = "desktop",
|
||||
feature = "mobile",
|
||||
feature = "web",
|
||||
feature = "fullstack",
|
||||
feature = "static-generation"
|
||||
))),
|
||||
deprecated(
|
||||
note = "No renderer is enabled. You must enable a renderer feature on the dioxus crate before calling the launch function.\nAdd `web`, `desktop`, `mobile`, `fullstack`, or `static-generation` to the `features` of dioxus field in your Cargo.toml.\n# Example\n```toml\n# ...\n[dependencies]\ndioxus = { version = \"0.5.0\", features = [\"web\"] }\n# ...\n```"
|
||||
)
|
||||
)]
|
||||
pub fn launch(app: fn() -> Element) -> $($return_type)* {
|
||||
#[allow(deprecated)]
|
||||
LaunchBuilder::new().launch(app)
|
||||
|
@ -439,29 +304,40 @@ impl_launch!(());
|
|||
impl_launch!(!);
|
||||
|
||||
#[cfg(feature = "web")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "web")))]
|
||||
/// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
pub fn launch_web(app: fn() -> Element) {
|
||||
LaunchBuilder::web().launch(app)
|
||||
}
|
||||
fn web_launch(
|
||||
root: fn() -> dioxus_core::Element,
|
||||
contexts: Vec<super::ContextFn>,
|
||||
platform_config: Vec<Box<dyn std::any::Any>>,
|
||||
) {
|
||||
// If the server feature is enabled, launch the client with hydration enabled
|
||||
#[cfg(any(feature = "static-generation", feature = "fullstack"))]
|
||||
{
|
||||
let platform_config = platform_config
|
||||
.into_iter()
|
||||
.find_map(|cfg| cfg.downcast::<dioxus_web::Config>().ok())
|
||||
.unwrap_or_default()
|
||||
.hydrate(true);
|
||||
|
||||
#[cfg(feature = "desktop")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "desktop")))]
|
||||
/// Launch your desktop application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
pub fn launch_desktop(app: fn() -> Element) {
|
||||
LaunchBuilder::desktop().launch(app)
|
||||
}
|
||||
let factory = move || {
|
||||
let mut vdom = dioxus_core::VirtualDom::new(root);
|
||||
for context in contexts {
|
||||
vdom.insert_any_root_context(context());
|
||||
}
|
||||
#[cfg(feature = "document")]
|
||||
{
|
||||
#[cfg(feature = "fullstack")]
|
||||
use dioxus_fullstack::document;
|
||||
#[cfg(all(feature = "static-generation", not(feature = "fullstack")))]
|
||||
use dioxus_static_site_generation::document;
|
||||
let document = std::rc::Rc::new(document::web::FullstackWebDocument)
|
||||
as std::rc::Rc<dyn crate::prelude::Document>;
|
||||
vdom.provide_root_context(document);
|
||||
}
|
||||
vdom
|
||||
};
|
||||
|
||||
#[cfg(feature = "fullstack")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "fullstack")))]
|
||||
/// Launch your fullstack application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
pub fn launch_fullstack(app: fn() -> Element) {
|
||||
LaunchBuilder::fullstack().launch(app)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mobile")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "mobile")))]
|
||||
/// Launch your mobile application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
pub fn launch_mobile(app: fn() -> Element) {
|
||||
LaunchBuilder::mobile().launch(app)
|
||||
dioxus_web::launch::launch_virtual_dom(factory(), platform_config)
|
||||
}
|
||||
#[cfg(not(any(feature = "static-generation", feature = "fullstack")))]
|
||||
dioxus_web::launch::launch(root, contexts, platform_config);
|
||||
}
|
||||
|
|
|
@ -34,8 +34,7 @@ mod launch;
|
|||
|
||||
#[cfg(feature = "launch")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "launch")))]
|
||||
#[allow(deprecated)]
|
||||
pub use launch::launch;
|
||||
pub use crate::launch::*;
|
||||
|
||||
#[cfg(feature = "hooks")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "hooks")))]
|
||||
|
@ -60,9 +59,6 @@ pub use dioxus_html as html;
|
|||
pub use dioxus_core_macro as core_macro;
|
||||
|
||||
pub mod prelude {
|
||||
#[cfg(feature = "launch")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "launch")))]
|
||||
pub use crate::launch::*;
|
||||
|
||||
#[cfg(feature = "hooks")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "hooks")))]
|
||||
|
|
|
@ -37,7 +37,77 @@ Full stack Dioxus in under 30 lines of code
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
launch(App);
|
||||
dioxus::launch(App);
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
let mut meaning = use_signal(|| None);
|
||||
|
||||
rsx! {
|
||||
h1 { "Meaning of life: {meaning:?}" }
|
||||
button {
|
||||
onclick: move |_| async move {
|
||||
if let Ok(data) = get_meaning("life the universe and everything".into()).await {
|
||||
meaning.set(data);
|
||||
}
|
||||
},
|
||||
"Run a server function"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[server]
|
||||
async fn get_meaning(of: String) -> Result<Option<u32>, ServerFnError> {
|
||||
Ok(of.contains("life").then(|| 42))
|
||||
}
|
||||
```
|
||||
|
||||
## Axum Integration
|
||||
|
||||
If you have an existing Axum router or you need more control over the server, you can use the [`DioxusRouterExt`](https://docs.rs/dioxus-fullstack/0.6.0-alpha.2/dioxus_fullstack/prelude/trait.DioxusRouterExt.html) trait to integrate with your existing Axum router.
|
||||
|
||||
First, make sure your `axum` dependency is optional and enabled by the server feature flag. Axum cannot be compiled to wasm, so if it is enabled by default, it will cause a compile error:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
dioxus = { version = "*", features = ["fullstack"] }
|
||||
axum = { version = "0.7.0", optional = true }
|
||||
|
||||
[features]
|
||||
server = ["dep:axum", "dioxus/server"]
|
||||
web = ["dioxus/web"]
|
||||
```
|
||||
|
||||
Then we can set up dioxus with the axum server:
|
||||
|
||||
```rust, no_run
|
||||
#![allow(non_snake_case)]
|
||||
use dioxus::prelude::*;
|
||||
|
||||
// The entry point for the server
|
||||
#[cfg(feature = "server")]
|
||||
fn main() {
|
||||
// Get the address the server should run on. If the CLI is running, the CLI proxies fullstack into the main address
|
||||
// and we use the generated address the CLI gives us
|
||||
let address = dioxus_cli_config::RuntimeCLIArguments::fullstack_address_or_localhost();
|
||||
|
||||
// Set up the axum router
|
||||
let router = axum::Router::new()
|
||||
// You can add a dioxus application to the router with the `serve_dioxus_application` method
|
||||
// This will add a fallback route to the router that will serve your component and server functions
|
||||
.serve_dioxus_application(ServeConfigBuilder::default(), App);
|
||||
|
||||
// Finally, we can launch the server
|
||||
let router = router.into_make_service();
|
||||
let listener = tokio::net::TcpListener::bind(address).await.unwrap();
|
||||
axum::serve(listener, router).await.unwrap();
|
||||
}
|
||||
|
||||
// For any other platform, we just launch the app
|
||||
#[cfg(not(feature = "server"))]
|
||||
fn main() {
|
||||
dioxus::launch(App);
|
||||
}
|
||||
|
||||
#[component]
|
||||
|
@ -111,7 +181,7 @@ fn main() {
|
|||
// For any other platform, we just launch the app
|
||||
#[cfg(not(feature = "server"))]
|
||||
fn main() {
|
||||
launch(App);
|
||||
dioxus::launch(App);
|
||||
}
|
||||
|
||||
#[component]
|
||||
|
|
|
@ -1,289 +0,0 @@
|
|||
//! Launch helper macros for fullstack apps
|
||||
#![allow(unused)]
|
||||
use crate::prelude::*;
|
||||
use dioxus_lib::prelude::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Settings for a fullstack app.
|
||||
///
|
||||
/// Depending on what features are enabled, you can pass in configurations for each client platform as well as the server:
|
||||
/// ```rust, no_run
|
||||
/// # fn app() -> Element { todo!() }
|
||||
/// use dioxus::prelude::*;
|
||||
///
|
||||
/// let mut cfg = dioxus::fullstack::Config::new();
|
||||
///
|
||||
/// // Only set the server config if the server feature is enabled
|
||||
/// server_only! {
|
||||
/// cfg = cfg.with_server_config(ServeConfigBuilder::default());
|
||||
/// }
|
||||
///
|
||||
/// // Only set the web config if the web feature is enabled
|
||||
/// web! {
|
||||
/// cfg = cfg.with_web_config(dioxus::web::Config::default());
|
||||
/// }
|
||||
///
|
||||
/// // Only set the desktop config if the desktop feature is enabled
|
||||
/// desktop! {
|
||||
/// cfg = cfg.with_desktop_config(dioxus::desktop::Config::default());
|
||||
/// }
|
||||
///
|
||||
/// // Finally, launch the app with the config
|
||||
/// LaunchBuilder::new()
|
||||
/// .with_cfg(cfg)
|
||||
/// .launch(app);
|
||||
/// ```
|
||||
pub struct Config {
|
||||
#[cfg(feature = "server")]
|
||||
pub(crate) server_cfg: ServeConfigBuilder,
|
||||
|
||||
#[cfg(feature = "web")]
|
||||
pub(crate) web_cfg: dioxus_web::Config,
|
||||
|
||||
#[cfg(feature = "desktop")]
|
||||
pub(crate) desktop_cfg: dioxus_desktop::Config,
|
||||
|
||||
#[cfg(feature = "mobile")]
|
||||
pub(crate) mobile_cfg: dioxus_mobile::Config,
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
#[cfg(feature = "server")]
|
||||
server_cfg: ServeConfigBuilder::new(),
|
||||
#[cfg(feature = "web")]
|
||||
web_cfg: dioxus_web::Config::default(),
|
||||
#[cfg(feature = "desktop")]
|
||||
desktop_cfg: dioxus_desktop::Config::default(),
|
||||
#[cfg(feature = "mobile")]
|
||||
mobile_cfg: dioxus_mobile::Config::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Create a new config for a fullstack app.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Set the incremental renderer config. The incremental config can be used to improve
|
||||
/// performance of heavy routes by caching the rendered html in memory and/or the file system.
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// # fn app() -> Element { todo!() }
|
||||
/// use dioxus::prelude::*;
|
||||
///
|
||||
/// let mut cfg = dioxus::fullstack::Config::new();
|
||||
///
|
||||
/// // Only set the server config if the server feature is enabled
|
||||
/// server_only! {
|
||||
/// cfg = cfg.incremental(IncrementalRendererConfig::default().with_memory_cache_limit(10000));
|
||||
/// }
|
||||
///
|
||||
/// // Finally, launch the app with the config
|
||||
/// LaunchBuilder::new()
|
||||
/// .with_cfg(cfg)
|
||||
/// .launch(app);
|
||||
/// ```
|
||||
#[cfg(feature = "server")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "server")))]
|
||||
pub fn incremental(self, cfg: IncrementalRendererConfig) -> Self {
|
||||
Self {
|
||||
server_cfg: self.server_cfg.incremental(cfg),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the server config
|
||||
/// ```rust, no_run
|
||||
/// # fn app() -> Element { todo!() }
|
||||
/// use dioxus::prelude::*;
|
||||
///
|
||||
/// let mut cfg = dioxus::fullstack::Config::new();
|
||||
///
|
||||
/// // Only set the server config if the server feature is enabled
|
||||
/// server_only! {
|
||||
/// cfg = cfg.with_server_config(ServeConfigBuilder::default());
|
||||
/// }
|
||||
///
|
||||
/// // Finally, launch the app with the config
|
||||
/// LaunchBuilder::new()
|
||||
/// .with_cfg(cfg)
|
||||
/// .launch(app);
|
||||
/// ```
|
||||
#[cfg(feature = "server")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "server")))]
|
||||
pub fn with_server_config(self, server_cfg: ServeConfigBuilder) -> Self {
|
||||
Self { server_cfg, ..self }
|
||||
}
|
||||
|
||||
/// Set the server config by modifying the config in place
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// # fn app() -> Element { todo!() }
|
||||
/// use dioxus::prelude::*;
|
||||
///
|
||||
/// let mut cfg = dioxus::fullstack::Config::new();
|
||||
///
|
||||
/// // Only set the server config if the server feature is enabled
|
||||
/// server_only! {
|
||||
/// cfg.set_server_config(ServeConfigBuilder::default());
|
||||
/// }
|
||||
///
|
||||
/// // Finally, launch the app with the config
|
||||
/// LaunchBuilder::new()
|
||||
/// .with_cfg(cfg)
|
||||
/// .launch(app);
|
||||
/// ```
|
||||
#[cfg(feature = "server")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "server")))]
|
||||
pub fn set_server_config(&mut self, server_cfg: ServeConfigBuilder) {
|
||||
self.server_cfg = server_cfg;
|
||||
}
|
||||
|
||||
/// Set the web config
|
||||
/// ```rust, no_run
|
||||
/// # fn app() -> Element { todo!() }
|
||||
/// use dioxus::prelude::*;
|
||||
///
|
||||
/// let mut cfg = dioxus::fullstack::Config::new();
|
||||
///
|
||||
/// // Only set the web config if the server feature is enabled
|
||||
/// web! {
|
||||
/// cfg = cfg.with_web_config(dioxus::web::Config::default());
|
||||
/// }
|
||||
///
|
||||
/// // Finally, launch the app with the config
|
||||
/// LaunchBuilder::new()
|
||||
/// .with_cfg(cfg)
|
||||
/// .launch(app);
|
||||
/// ```
|
||||
#[cfg(feature = "web")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "web")))]
|
||||
pub fn with_web_config(self, web_cfg: dioxus_web::Config) -> Self {
|
||||
Self { web_cfg, ..self }
|
||||
}
|
||||
|
||||
/// Set the server config by modifying the config in place
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// # fn app() -> Element { todo!() }
|
||||
/// use dioxus::prelude::*;
|
||||
///
|
||||
/// let mut cfg = dioxus::fullstack::Config::new();
|
||||
///
|
||||
/// // Only set the web config if the server feature is enabled
|
||||
/// web! {
|
||||
/// cfg.set_web_config(dioxus::web::Config::default());
|
||||
/// }
|
||||
///
|
||||
/// // Finally, launch the app with the config
|
||||
/// LaunchBuilder::new()
|
||||
/// .with_cfg(cfg)
|
||||
/// .launch(app);
|
||||
/// ```
|
||||
#[cfg(feature = "web")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "web")))]
|
||||
pub fn set_web_config(&mut self, web_cfg: dioxus_web::Config) {
|
||||
self.web_cfg = web_cfg;
|
||||
}
|
||||
|
||||
/// Set the desktop config
|
||||
/// ```rust, no_run
|
||||
/// # fn app() -> Element { todo!() }
|
||||
/// use dioxus::prelude::*;
|
||||
///
|
||||
/// let mut cfg = dioxus::fullstack::Config::new();
|
||||
///
|
||||
/// // Only set the desktop config if the server feature is enabled
|
||||
/// desktop! {
|
||||
/// cfg = cfg.with_desktop_config(dioxus::desktop::Config::default());
|
||||
/// }
|
||||
///
|
||||
/// // Finally, launch the app with the config
|
||||
/// LaunchBuilder::new()
|
||||
/// .with_cfg(cfg)
|
||||
/// .launch(app);
|
||||
/// ```
|
||||
#[cfg(feature = "desktop")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "desktop")))]
|
||||
pub fn with_desktop_config(self, desktop_cfg: dioxus_desktop::Config) -> Self {
|
||||
Self {
|
||||
desktop_cfg,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the desktop config by modifying the config in place
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// # fn app() -> Element { todo!() }
|
||||
/// use dioxus::prelude::*;
|
||||
///
|
||||
/// let mut cfg = dioxus::fullstack::Config::new();
|
||||
///
|
||||
/// // Only set the desktop config if the server feature is enabled
|
||||
/// desktop! {
|
||||
/// cfg.set_desktop_config(dioxus::desktop::Config::default());
|
||||
/// }
|
||||
///
|
||||
/// // Finally, launch the app with the config
|
||||
/// LaunchBuilder::new()
|
||||
/// .with_cfg(cfg)
|
||||
/// .launch(app);
|
||||
/// ```
|
||||
#[cfg(feature = "desktop")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "desktop")))]
|
||||
pub fn set_desktop_config(&mut self, desktop_cfg: dioxus_desktop::Config) {
|
||||
self.desktop_cfg = desktop_cfg;
|
||||
}
|
||||
|
||||
/// Set the mobile config
|
||||
/// ```rust, no_run
|
||||
/// # fn app() -> Element { todo!() }
|
||||
/// use dioxus::prelude::*;
|
||||
///
|
||||
/// let mut cfg = dioxus::fullstack::Config::new();
|
||||
///
|
||||
/// // Only set the mobile config if the server feature is enabled
|
||||
/// mobile! {
|
||||
/// cfg = cfg.with_mobile_cfg(dioxus::mobile::Config::default());
|
||||
/// }
|
||||
///
|
||||
/// // Finally, launch the app with the config
|
||||
/// LaunchBuilder::new()
|
||||
/// .with_cfg(cfg)
|
||||
/// .launch(app);
|
||||
/// Set the mobile config.
|
||||
#[cfg(feature = "mobile")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "mobile")))]
|
||||
pub fn with_mobile_cfg(self, mobile_cfg: dioxus_mobile::Config) -> Self {
|
||||
Self { mobile_cfg, ..self }
|
||||
}
|
||||
|
||||
/// Set the mobile config by modifying the config in place
|
||||
/// ```rust, no_run
|
||||
/// # fn app() -> Element { todo!() }
|
||||
/// use dioxus::prelude::*;
|
||||
///
|
||||
/// let mut cfg = dioxus::fullstack::Config::new();
|
||||
///
|
||||
/// // Only set the mobile config if the server feature is enabled
|
||||
/// mobile! {
|
||||
/// cfg.set_mobile_cfg(dioxus::mobile::Config::default());
|
||||
/// }
|
||||
///
|
||||
/// // Finally, launch the app with the config
|
||||
/// LaunchBuilder::new()
|
||||
/// .with_cfg(cfg)
|
||||
/// .launch(app);
|
||||
/// Set the mobile config.
|
||||
#[cfg(feature = "mobile")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "mobile")))]
|
||||
pub fn set_mobile_cfg(&mut self, mobile_cfg: dioxus_mobile::Config) {
|
||||
self.mobile_cfg = mobile_cfg;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
//! This module contains the document providers for the fullstack platform.
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
pub(crate) mod server;
|
||||
pub mod server;
|
||||
#[cfg(feature = "server")]
|
||||
pub use server::ServerDocument;
|
||||
#[cfg(all(feature = "web", feature = "document"))]
|
||||
pub(crate) mod web;
|
||||
pub mod web;
|
||||
|
|
|
@ -11,7 +11,8 @@ fn head_element_written_on_server() -> bool {
|
|||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub(crate) struct FullstackWebDocument;
|
||||
/// A document provider for fullstack web clients
|
||||
pub struct FullstackWebDocument;
|
||||
|
||||
impl Document for FullstackWebDocument {
|
||||
fn new_evaluator(
|
||||
|
|
|
@ -1,171 +0,0 @@
|
|||
//! This module contains the `launch` function, which is the main entry point for dioxus fullstack
|
||||
|
||||
use std::{any::Any, sync::Arc};
|
||||
|
||||
use dioxus_lib::prelude::{Element, VirtualDom};
|
||||
|
||||
pub use crate::Config;
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) type ContextProviders = Arc<
|
||||
Vec<Box<dyn Fn() -> Box<dyn std::any::Any + Send + Sync + 'static> + Send + Sync + 'static>>,
|
||||
>;
|
||||
|
||||
#[allow(unused)]
|
||||
fn virtual_dom_factory(
|
||||
root: fn() -> Element,
|
||||
contexts: ContextProviders,
|
||||
) -> impl Fn() -> VirtualDom + 'static {
|
||||
move || {
|
||||
let mut vdom = VirtualDom::new(root);
|
||||
for context in &*contexts {
|
||||
vdom.insert_any_root_context(context());
|
||||
}
|
||||
vdom
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
/// 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,
|
||||
) -> ! {
|
||||
let contexts = Arc::new(contexts);
|
||||
let factory = virtual_dom_factory(root, contexts.clone());
|
||||
#[cfg(all(feature = "server", not(target_arch = "wasm32")))]
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async move {
|
||||
launch_server(platform_config, factory, contexts).await;
|
||||
});
|
||||
|
||||
unreachable!("Launching a fullstack app should never return")
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "server"), feature = "web"))]
|
||||
/// Launch a fullstack app with the given root component, contexts, and config.
|
||||
#[allow(unused)]
|
||||
pub fn launch(
|
||||
root: fn() -> Element,
|
||||
#[allow(unused_mut)] mut contexts: Vec<
|
||||
Box<dyn Fn() -> Box<dyn Any + Send + Sync> + Send + Sync>,
|
||||
>,
|
||||
platform_config: Config,
|
||||
) {
|
||||
let contexts = Arc::new(contexts);
|
||||
let mut factory = virtual_dom_factory(root, contexts);
|
||||
let cfg = platform_config.web_cfg.hydrate(true);
|
||||
|
||||
#[cfg(feature = "document")]
|
||||
let factory = move || {
|
||||
let mut vdom = factory();
|
||||
let document = std::rc::Rc::new(crate::document::web::FullstackWebDocument)
|
||||
as std::rc::Rc<dyn dioxus_lib::prelude::document::Document>;
|
||||
vdom.provide_root_context(document);
|
||||
vdom
|
||||
};
|
||||
|
||||
dioxus_web::launch::launch_virtual_dom(factory(), cfg)
|
||||
}
|
||||
|
||||
#[cfg(all(not(any(feature = "server", feature = "web")), feature = "desktop"))]
|
||||
/// 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,
|
||||
) -> ! {
|
||||
let contexts = Arc::new(contexts);
|
||||
let factory = virtual_dom_factory(root, contexts);
|
||||
let cfg = platform_config.desktop_cfg;
|
||||
dioxus_desktop::launch::launch_virtual_dom(factory(), cfg)
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "server", feature = "web", feature = "desktop")),
|
||||
feature = "mobile"
|
||||
))]
|
||||
/// 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,
|
||||
) -> ! {
|
||||
let contexts = Arc::new(contexts);
|
||||
let factory = virtual_dom_factory(root, contexts.clone());
|
||||
let cfg = platform_config.mobile_cfg;
|
||||
dioxus_mobile::launch::launch_virtual_dom(factory(), cfg)
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
feature = "server",
|
||||
feature = "web",
|
||||
feature = "desktop",
|
||||
feature = "mobile"
|
||||
)))]
|
||||
/// 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,
|
||||
) -> ! {
|
||||
panic!("No platform feature enabled. Please enable one of the following features: axum, desktop, or web to use the launch API.")
|
||||
}
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
#[allow(unused)]
|
||||
/// Launch a server application
|
||||
async fn launch_server(
|
||||
platform_config: Config,
|
||||
build_virtual_dom: impl Fn() -> VirtualDom + Send + Sync + 'static,
|
||||
context_providers: ContextProviders,
|
||||
) {
|
||||
// Get the address the server should run on. If the CLI is running, the CLI proxies fullstack into the main address
|
||||
// and we use the generated address the CLI gives us
|
||||
let address = dioxus_cli_config::fullstack_address_or_localhost();
|
||||
|
||||
#[cfg(feature = "axum")]
|
||||
{
|
||||
use crate::axum_adapter::DioxusRouterExt;
|
||||
|
||||
#[allow(unused_mut)]
|
||||
let mut router =
|
||||
axum::Router::new().register_server_functions_with_context(context_providers);
|
||||
|
||||
#[cfg(not(any(feature = "desktop", feature = "mobile")))]
|
||||
{
|
||||
use crate::prelude::RenderHandleState;
|
||||
use crate::prelude::SSRState;
|
||||
|
||||
match platform_config.server_cfg.build() {
|
||||
Ok(cfg) => {
|
||||
router = router.serve_static_assets();
|
||||
|
||||
router = router.fallback(
|
||||
axum::routing::get(crate::axum_adapter::render_handler).with_state(
|
||||
RenderHandleState::new_with_virtual_dom_factory(cfg, build_virtual_dom),
|
||||
),
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::trace!("Failed to create render handler. This is expected if you are only using fullstack for desktop/mobile server functions: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let router = router.into_make_service();
|
||||
let listener = tokio::net::TcpListener::bind(address).await.unwrap();
|
||||
|
||||
axum::serve(listener, router).await.unwrap();
|
||||
}
|
||||
#[cfg(not(feature = "axum"))]
|
||||
{
|
||||
panic!("Launching with dioxus fullstack requires the axum feature. If you are using a community fullstack adapter, please check the documentation for that adapter to see how to launch the application.");
|
||||
}
|
||||
}
|
|
@ -10,13 +10,9 @@ mod html_storage;
|
|||
|
||||
#[cfg(feature = "axum")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "axum")))]
|
||||
mod axum_adapter;
|
||||
pub mod server;
|
||||
|
||||
mod config;
|
||||
mod hooks;
|
||||
pub mod launch;
|
||||
|
||||
pub use config::*;
|
||||
|
||||
pub mod document;
|
||||
#[cfg(feature = "server")]
|
||||
|
@ -39,7 +35,7 @@ pub mod prelude {
|
|||
|
||||
#[cfg(feature = "axum")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "axum")))]
|
||||
pub use crate::axum_adapter::*;
|
||||
pub use crate::server::*;
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "server")))]
|
||||
|
|
|
@ -5,6 +5,8 @@ use std::fs::File;
|
|||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use dioxus_lib::prelude::dioxus_core::LaunchConfig;
|
||||
|
||||
/// A ServeConfig is used to configure how to serve a Dioxus application. It contains information about how to serve static assets, and what content to render with [`dioxus-ssr`].
|
||||
#[derive(Clone, Default)]
|
||||
pub struct ServeConfigBuilder {
|
||||
|
@ -14,6 +16,8 @@ pub struct ServeConfigBuilder {
|
|||
pub(crate) incremental: Option<dioxus_isrg::IncrementalRendererConfig>,
|
||||
}
|
||||
|
||||
impl LaunchConfig for ServeConfigBuilder {}
|
||||
|
||||
impl ServeConfigBuilder {
|
||||
/// Create a new ServeConfigBuilder with incremental static generation disabled and the default index.html settings
|
||||
pub fn new() -> Self {
|
||||
|
@ -239,6 +243,8 @@ pub struct ServeConfig {
|
|||
pub(crate) incremental: Option<dioxus_isrg::IncrementalRendererConfig>,
|
||||
}
|
||||
|
||||
impl LaunchConfig for ServeConfig {}
|
||||
|
||||
impl ServeConfig {
|
||||
/// Create a new ServeConfig
|
||||
pub fn new() -> Result<Self, UnableToLoadIndex> {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue